From: Husam <husamsenussi@gmail.com>
To: Tony Lindgren <tony@atomide.com>
Cc: linux-omap-open-source@linux.omap.com
Subject: Re: Reading/Writing to MMC without interrupt handler
Date: Mon, 3 Apr 2006 21:52:42 +0100 [thread overview]
Message-ID: <200604032152.42890.husamsenussi@gmail.com> (raw)
In-Reply-To: <20060403142359.GB13009@atomide.com>
[-- Attachment #1: Type: text/plain, Size: 1314 bytes --]
Tony,
First of all thanks for the reply, I'm assuming you suggest I should double
the timeout !!!! I have done that but I did get the same result !!!
I have attached my code ... if someboday can have look at it, will be nice
Thanks Again,
On Monday 03 April 2006 15:24, Tony Lindgren wrote:
> * Husam <husamsenussi@gmail.com> [060401 04:53]:
> > Hi,
> >
> > I guess this stupid question, but I'm going to asked anyway :)
> >
> > I'm adding ipaq h6300 support to u-boot which based OMAP1510 processer, I
> > want to allow u-boot to load an kernel image from MMC/SD card.
> >
> > I did make the changes but I'm having problem reading from the MMC card
> > (Getting Data Timeout) ,
> >
> > At the moment I'm polling for the status without using irq, and that
> > seems to work for configuring the card and reading manufacturer
> > information like date, serial number etc.
> >
> > mca_vsn : 03
> > cmdclass : 1F5
> > tacc_clks: 00
> > tacc_ns : 4C4B400
> > max_dtr : 1312D00
> > read_blkbits: 9
> > capacity : 1003520
> > Manufacturer ID = 0000049A
> > HW/FW Revision = 0 0
> > Product Name = MMC
> > Serial Number = 0000049a
> > Month = 12
> > Year = 2004
> >
> > My question is it passible to do that without having to enable irq and
> > using interrupt handler?
>
> Yes, it should be doable.
>
> Tony
[-- Attachment #2: mmc.c --]
[-- Type: text/x-csrc, Size: 21166 bytes --]
#include <config.h>
#include <common.h>
#if defined(CONFIG_MMC)
#include <asm/arch/hardware.h>
#include <linux/mmc/mmc.h>
#include <linux/mmc/protocol.h>
#include <linux/string.h>
#include <malloc.h>
#include <asm/errno.h>
#include <part.h>
#include <i2c.h>
#define CONFIG_MMC_DEBUG
#if defined(CONFIG_MMC_DEBUG)
#define DBG(fmt,args...) printf(fmt,##args)
#else
#define DBG(fmt,args...) while(0) {}
#endif
extern int
fat_register_device(block_dev_desc_t *dev_desc, int part_no);
static block_dev_desc_t *mmc_dev;
#define UNSTUFF_BITS(resp,start,size) \
({ \
const int __size = size; \
const u32 __mask = (__size < 32 ? 1 << __size : 0) - 1; \
const int __off = 3 - ((start) / 32); \
const int __shft = (start) & 31; \
u32 __res; \
\
__res = resp[__off] >> __shft; \
if (__size + __shft > 32) \
__res |= resp[__off-1] << ((32 - __shft) % 32); \
__res & __mask; \
})
/*
* OCR Bit positions to 10s of Vdd mV.
*/
static const unsigned short mmc_ocr_bit_to_vdd[] = {
150, 155, 160, 165, 170, 180, 190, 200,
210, 220, 230, 240, 250, 260, 270, 280,
290, 300, 310, 320, 330, 340, 350, 360
};
static const unsigned int tran_exp[] = {
10000, 100000, 1000000, 10000000,
0, 0, 0, 0
};
static const unsigned char tran_mant[] = {
0, 10, 12, 13, 15, 20, 25, 30,
35, 40, 45, 50, 55, 60, 70, 80,
};
static const unsigned int tacc_exp[] = {
1, 10, 100, 1000, 10000, 100000, 1000000, 10000000,
};
static const unsigned int tacc_mant[] = {
0, 10, 12, 13, 15, 20, 25, 30,
35, 40, 45, 50, 55, 60, 70, 80,
};
typedef struct _mmc_command_t {
uint16_t code;
uint16_t resptype;
uint32_t resp[4];
uint32_t left;
uint32_t size;
uint16_t *buffer;
uint32_t error;
uint32_t __lock;
}mmc_command_t;
typedef struct _mmc_card_t {
int is_sd;
uint32_t status; // card status
uint16_t cmd; // last request command
uint16_t resp; // Response type
mmc_command_t command;
mmc_csd_t csd;
mmc_cid_t cid;
}mmc_card_t;
mmc_card_t card;
static void mmc_decode_csd(mmc_card_t *card, uint32_t *resp)
{
mmc_csd_t *csd = &card->csd;
unsigned int e, m, csd_struct;
/*
* We only understand CSD structure v1.1 and v2.
* v2 has extra information in bits 15, 11 and 10.
*/
csd_struct = UNSTUFF_BITS(resp, 126, 2);
if (csd_struct != 1 && csd_struct != 2) {
printf("unrecognised CSD structure version %d\n", csd_struct);
return;
}
csd->mmca_vsn = UNSTUFF_BITS(resp, 122, 4);
m = UNSTUFF_BITS(resp, 115, 4);
e = UNSTUFF_BITS(resp, 112, 3);
csd->tacc_ns = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
csd->tacc_clks = UNSTUFF_BITS(resp, 104, 8) * 100;
m = UNSTUFF_BITS(resp, 99, 4);
e = UNSTUFF_BITS(resp, 96, 3);
csd->max_dtr = tran_exp[e] * tran_mant[m];
csd->cmdclass = UNSTUFF_BITS(resp, 84, 12);
e = UNSTUFF_BITS(resp, 47, 3);
m = UNSTUFF_BITS(resp, 62, 12);
csd->capacity = (1 + m) << (e + 2);
csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
#if defined(CONFIG_MMC_DEBUG)
printf("mmca_vsn : %02X\n", csd->mmca_vsn);
printf("cmdclass : %02X\n", csd->cmdclass);
printf("tacc_clks: %02X\n", csd->tacc_clks);
printf("tacc_ns : %04X\n", csd->tacc_ns);
printf("max_dtr : %04X\n", csd->max_dtr);
printf("read_blkbits: %u\n", csd->read_blkbits);
printf("capacity : %u\n", csd->capacity);
#endif
}
static void mmc_decode_cid(mmc_card_t *card, uint32_t *resp) {
memset(&card->cid, 0, sizeof(mmc_cid_t));
/*
* The selection of the format here is guesswork based upon
* information people have sent to date.
*/
switch (card->csd.mmca_vsn) {
case 0: /* MMC v1.? */
case 1: /* MMC v1.4 */
card->cid.manfid = UNSTUFF_BITS(resp, 104, 24);
card->cid.prod_name[0] = UNSTUFF_BITS(resp, 96, 8);
card->cid.prod_name[1] = UNSTUFF_BITS(resp, 88, 8);
card->cid.prod_name[2] = UNSTUFF_BITS(resp, 80, 8);
card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8);
card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8);
card->cid.prod_name[5] = UNSTUFF_BITS(resp, 56, 8);
card->cid.prod_name[6] = UNSTUFF_BITS(resp, 48, 8);
card->cid.hwrev = UNSTUFF_BITS(resp, 44, 4);
card->cid.fwrev = UNSTUFF_BITS(resp, 40, 4);
card->cid.serial = UNSTUFF_BITS(resp, 16, 24);
card->cid.month = UNSTUFF_BITS(resp, 12, 4);
card->cid.year = UNSTUFF_BITS(resp, 8, 4) + 1997;
break;
case 2: /* MMC v2.x ? */
case 3: /* MMC v3.x ? */
card->cid.manfid = UNSTUFF_BITS(resp, 120, 8);
card->cid.oemid = UNSTUFF_BITS(resp, 104, 16);
card->cid.prod_name[0] = UNSTUFF_BITS(resp, 96, 8);
card->cid.prod_name[1] = UNSTUFF_BITS(resp, 88, 8);
card->cid.prod_name[2] = UNSTUFF_BITS(resp, 80, 8);
card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8);
card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8);
card->cid.prod_name[5] = UNSTUFF_BITS(resp, 56, 8);
card->cid.serial = UNSTUFF_BITS(resp, 16, 32);
card->cid.month = UNSTUFF_BITS(resp, 12, 4);
card->cid.year = UNSTUFF_BITS(resp, 8, 4) + 1997;
break;
default:
printf("card has unknown MMCA version %d\n",
card->csd.mmca_vsn);
break;
}
#if defined(CONFIG_MMC_DEBUG)
printf("MMC found. Card desciption is:\n");
printf("Manufacturer ID = %08X\n", card->cid.serial);
printf("HW/FW Revision = %x %x\n",card->cid.hwrev, card->cid.fwrev);
printf("Product Name = %s\n",card->cid.prod_name);
printf("Serial Number = %08x\n", card->cid.serial);
printf("Month = %d\n",card->cid.month);
printf("Year = %d\n",card->cid.year);
#endif
}
#if !defined(CONFIG_MMC_IRQ)
void mmc_dma_irq(dma_channel_t *ch, uint16_t status){
// Save channel status
ch->status = status;
// Free channel
dma_ch_free(ch->id);
// Unlock channel
__spin_unlock(&ch->lock);
}
#endif
#if !defined(CONFIG_MMC_IRQ)
static void start_dma_transfer(uint8_t *buffer, int blocks, int isread){
uint16_t dev = isread? OMAP_DMA_MMC_RX : OMAP_DMA_MMC_TX;
// Setup channel 0
dma_ch_setup(MMC_DMA_CH, dev, mmc_dma_irq);
// Setup Source and destination
if (isread) {
/* 16 frames/block, 32 bytes/frame */
dma_ch_set_src(MMC_DMA_CH,
OMAP_DMA_PORT_TIPB,
OMAP_DMA_AMODE_CONSTANT,
MMC_REG_DATA);
dma_ch_set_dest(MMC_DMA_CH, OMAP_DMA_PORT_EMIFF,
OMAP_DMA_AMODE_POST_INC,
virt_to_phys((uint32_t) buffer));
MMC_BUF = 0x8f0f;
} else {
dma_ch_set_dest(MMC_DMA_CH, OMAP_DMA_PORT_TIPB,
OMAP_DMA_AMODE_CONSTANT,
MMC_REG_DATA);
dma_ch_set_src(MMC_DMA_CH, OMAP_DMA_PORT_EMIFF,
OMAP_DMA_AMODE_POST_INC,
virt_to_phys((uint32_t) buffer));
MMC_BUF = 0x0f8f;
}
dma_set_transfer_params(MMC_DMA_CH, OMAP_DMA_DATA_TYPE_S16, 16,
16 * blocks,
OMAP_DMA_SYNC_FRAME);
dma_ch_start(MMC_DMA_CH);
}
#endif
void mmc_command_start(uint16_t cmd, uint32_t arg, uint16_t resptype){
/* Constract register command */
uint16_t cmdreg = 0 | resptype;
card.command.code = cmd;
card.command.resptype = resptype;
card.command.error = 0;
if(((cmd == MMC_SEND_OP_COND) ||
(cmd == MMC_ALL_SEND_CID) ||
(cmd == MMC_SET_RELATIVE_ADDR) ||
(cmd == MMC_GO_IRQ_STATE)) && !card.is_sd)
{
/* Set Open Drain Mode for MMC commands 1,2,3,40 */
cmdreg |= (1 << 6);
}
/* Set command type */
switch(cmd) {
case MMC_RESET:
cmdreg |= 1 << 7;
cmd = MMC_GO_IDLE_STATE;
break;
case MMC_GO_IDLE_STATE:
case MMC_SET_DSR:
break;
case MMC_SEND_OP_COND:
case MMC_ALL_SEND_CID:
case MMC_GO_IRQ_STATE:
cmdreg |= 1 << 12;
break;
case MMC_READ_DAT_UNTIL_STOP:
case MMC_READ_SINGLE_BLOCK:
case MMC_READ_MULTIPLE_BLOCK:
case SD_SEND_SCR:
cmdreg |= 1 << 15 | 1 << 12 | 1 << 13;
break;
case MMC_WRITE_DAT_UNTIL_STOP:
case MMC_WRITE_BLOCK:
case MMC_WRITE_MULTIPLE_BLOCK:
case MMC_PROGRAM_CID:
case MMC_PROGRAM_CSD:
case MMC_SEND_WRITE_PROT:
case MMC_LOCK_UNLOCK:
case MMC_GEN_CMD:
cmdreg |= 1 << 12 | 1 << 13;
break;
default:
cmdreg |= 1 << 13;
}
/* Set command index */
cmdreg |= cmd;
/* Send Command to MMC host */
MMC_STAT_REG = 0xffff;
MMC_CTO_REG = 0xfd;
MMC_DTO_REG = 0xfffd;
MMC_ARGL_REG = arg & 0x0000ffff;
MMC_ARGH_REG = arg >> 16;
MMC_IE_REG = 0xffff;
MMC_CMD_REG = cmdreg;
}
void mmc_command_end(uint32_t resp[4]){
resp[0] = 0;
resp[1] = 0;
resp[2] = 0;
resp[3] = 0;
if(card.command.resptype == MMC_RESP_NONE){
return;
}else if(card.command.resptype == MMC_RESP_R2){
resp[3] = (MMC_RSP0_REG | (MMC_RSP1_REG << 16));
resp[2] = (MMC_RSP2_REG | (MMC_RSP3_REG << 16));
resp[1] = (MMC_RSP4_REG | (MMC_RSP5_REG << 16));
resp[0] = (MMC_RSP6_REG | (MMC_RSP7_REG << 16));
}else {
resp[0] = (MMC_RSP6_REG | ((uint32_t) MMC_RSP7_REG << 16));
}
#if defined(CONFIG_MMC_TRACE)
printf("Resp[0] : %08X\n", resp[0]);
printf("Resp[1] : %08X\n", resp[1]);
printf("Resp[2] : %08X\n", resp[2]);
printf("Resp[3] : %08X\n", resp[3]);
#endif
}
void omap_mmc_irq(void) {
uint16_t status = 0;
uint32_t command_done = FALSE;
uint32_t rw_done = FALSE;
mmc_command_t *cmd = &card.command;
while((status = MMC_STAT_REG) != 0){
/* Reset status Bits */
MMC_STAT_REG = status;
#if defined(CONFIG_MMC_DEBUG)
printf("cmd %02d, status %04X\n",
cmd->code, status);
#endif
if ((status & MMC_A_FULL) ||
((status & MMC_END_OF_DATA) && (cmd->left > 0))){
#if defined(CONFIG_MMC_IRQ)
/* Read data command */
uint32_t in = (cmd->left / 2);
if(in > 32){
in = 32;
}
cmd->left -= (in * 2);
cmd->size += (in * 2);
while(in-- > 0){
// Lets read from the card
*cmd->buffer = MMC_DATA_REG;
++cmd->buffer;
}
#endif
}
if (status & MMC_A_EMPTY) {
#if defined(CONFIG_MMC_IRQ)
/* Write data command */
uint32_t out = (cmd->left / 2);
if(out > 32){
out = 32;
}
cmd->left -= out;
while(out-- > 0){
// Lets write to card.
MMC_DATA_REG = *cmd->buffer;
++cmd->buffer;
}
#endif
}
if (status & MMC_END_OF_DATA) {
// Block sent/received
rw_done = TRUE;
}
if (status & MMC_DATA_TOUT) {
// Data timeout
if(cmd->buffer){
cmd->error |= MMC_ERR_TIMEOUT;
rw_done = TRUE;
printf("Data timeout\n");
}
}
if (status & MMC_DATA_CRC) {
if(cmd->buffer){
cmd->error |= MMC_ERR_BADCRC;
rw_done = TRUE;
printf("Data CRC error\n");
}
}
if (status & MMC_CMD_TOUT) {
#if defined(HAVE_MMC_IGNORE_CMD_TIMEOUT)
if(cmd->code != MMC_ALL_SEND_CID &&
cmd->code != MMC_SEND_OP_COND){
printf("Command timeout\n");
cmd->error |= MMC_ERR_TIMEOUT;
command_done = TRUE;
}
#else
cmd->error |= MMC_ERR_TIMEOUT;
command_done = TRUE;
#endif
}
if (status & MMC_CMD_CRC) {
// Command CRC error
cmd->error |= MMC_ERR_BADCRC;
command_done = TRUE;
printf("Command CRC error\n");
}
if (status & MMC_OCR_BUSY) {
// Some reason this condition
// is ignored in linux code!!
}
if (status & MMC_CARD_ERR) {
// Card status error
if(cmd->buffer){
rw_done = TRUE;
}else{
command_done = TRUE;
}
printf("Card error\n");
cmd->error |= MMC_ERR_FAILED;
}
if((status & MMC_END_OF_CMD) &&
(!(status & MMC_A_EMPTY))) {
// End of command phase
command_done = TRUE;
}
if(status & MMC_EOF_BUSY){
}
if(status & MMC_ENTER_BUSY){
}
}
if(command_done == TRUE && !cmd->buffer){
// Read response
mmc_command_end(cmd->resp);
if(!cmd->buffer){
// release the lock so
// the main routin can continue
cmd->__lock = 1;
}
}
if(rw_done == TRUE){
// Let's wakup the
// waitting task
cmd->__lock = 1;
}
}
uint32_t mmc_command_wait(mmc_card_t *card){
card->command.__lock = 0;
while(!card->command.__lock){
omap_mmc_irq();
}
// Resturn result.
return card->command.error;
}
uint32_t mmc_send_op_cond(mmc_card_t *card,int is_sd){
uint32_t ocr = 0;
uint32_t ret = MMC_ERR_NONE;
uint32_t cmd = is_sd? SD_SEND_OP_COND:MMC_SEND_OP_COND;
// This loop will keep sending
// MMC_SEND_OP_COND until we
// we manage to clear busy flag
do {
// Send MMC_SEND_OP_COND or SD_SEND_OP_COND command
mmc_command_start(cmd, ocr, MMC_RESP_R3);
// Wait for response
ret = mmc_command_wait(card);
if(ret & MMC_ERR_TIMEOUT){
// Command timeout
return MMC_ERR_TIMEOUT;
}
// Get the new ocr
ocr = card->command.resp[0];
}while((card->command.resp[0] & MMC_CARD_BUSY) == 0);
return MMC_ERR_NONE;
}
static uint32_t omap_mmc_stop(mmc_card_t *card){
uint32_t ret = 0;
// Stop Transmission
mmc_command_start(MMC_STOP_TRANSMISSION, 0,MMC_RESP_R1);
if((ret = mmc_command_wait(card)) != MMC_ERR_NONE){
printf("Failed to stop transmission\n");
return ret;
}
return 0;
}
uint32_t omap_mmc_data_request(mmc_card_t *card, uint16_t opcode, uint32_t src,
uint16_t nblks, uint16_t *buffer){
uint32_t ret = MMC_ERR_NONE;
// Disable DMA mode
MMC_BUF_REG = 0x1f1f;
// Set number of blocks and
// block size
MMC_NBLK_REG = (nblks - 1);
MMC_BLEN_REG = ((1 << card->csd.read_blkbits) - 1);
// Set data time
uint16_t reg = MMC_SDIO_REG;
uint32_t tmo = (card->csd.tacc_clks * 10) +
(card->csd.tacc_ns * 10) / 500;
tmo = (tmo << 4) * 2;
if(tmo > 0xffff){
reg |= (1 << 5);
tmo /= 1024;
}else {
reg |= ~(1 << 5);
}
MMC_DTO_REG = tmo; /* 0xfffd */
MMC_SDIO_REG = reg;
// Set data command buffer
card->command.buffer = buffer;
card->command.left = (nblks * (1 << card->csd.read_blkbits));
card->command.size = 0;
// block location
uint32_t loc = src << card->csd.read_blkbits;
// Lets start data command
mmc_command_start(opcode,loc,MMC_RESP_R1);
// Now just wait for the result
if((ret = mmc_command_wait(card)) != MMC_ERR_NONE){
printf("MMC read/write failed %d\n",ret);
card->command.buffer = NULL;
return ret;
}
// Reset buffer pointer
card->command.buffer = NULL;
if(nblks > 1){
ret = omap_mmc_stop(card);
}
return 0;
}
unsigned long omap_mmc_read(int dev,unsigned long start,
lbaint_t blkcnt,
unsigned long *buffer){
#if defined(CONFIG_MMC_IRQ)
// Lets try and read number of
// blocks, at some point i will replace
// the interrupt style with DMA.
uint16_t opcode = MMC_READ_SINGLE_BLOCK;
uint32_t ret = 0;
uint8_t *b = (uint8_t *) buffer;
DBG("Read from %d, %d block(s)\n", start,blkcnt);
while(blkcnt){
DBG("Read sector %d\n", start);
ret = omap_mmc_data_request(&card, opcode,
start,
1, (uint16_t *) b);
if(ret){
return ret;
}
b += 512;
start += 1;
blkcnt -= 1;
}
#else
uint16_t opcode = (blkcnt > 1) ? MMC_READ_MULTIPLE_BLOCK : MMC_READ_SINGLE_BLOCK;
uint32_t ret = 0;
ret = omap_mmc_data_request(&card, opcode,
start,
blkcnt, (uint16_t *) buffer);
if(ret){
return ret;
}
#endif
return 0;
}
uint32_t omap_mmc_write(uint16_t loc, uint16_t nblks, uint16_t *buffer){
// Lets try and write number of
// blocks.
return omap_mmc_data_request(&card, MMC_WRITE_MULTIPLE_BLOCK, loc, nblks, buffer);
}
static void omap_mmc_set_clock(uint32_t clock) {
uint32_t dsor = 48000000 / clock;
if(dsor < 1)
dsor = 1;
if (48000000 / dsor > clock)
dsor++;
if (dsor > 250)
dsor = 250;
// Enable power bit
dsor |= (1<<11);
// Now update MMC_CON
MMC_CON_REG = dsor;
MMC_CON_REG = dsor;
}
block_dev_desc_t *omap_mmc_init(int is_sd){
uint32_t raw_cid[4];
uint32_t raw_csd[4];
uint8_t val;
MMC_CON_REG = (120 | (1 << 11));
MMC_CON_REG = (120 | (1 << 11));
MMC_STAT_REG= 0xffff;
memset((void *) &card, 0, sizeof(mmc_card_t));
// Set type of card.
card.is_sd = is_sd;
// Reset device
DBG("MMC Reset\n");
mmc_command_start(MMC_RESET, 0, MMC_RESP_NONE);
if(mmc_command_wait(&card) != MMC_ERR_NONE){
printf("MMC card not avalible\n");
return NULL;
}
DBG("Go to idle\n");
mmc_command_start(MMC_GO_IDLE_STATE, 0,MMC_RESP_NONE);
if(mmc_command_wait(&card) != MMC_ERR_NONE){
printf("MMC card not avalible\n");
return NULL;
}
DBG("Send OP COND\n");
if(mmc_send_op_cond(&card,is_sd) != MMC_ERR_NONE){
return NULL;
}
DBG("Send CID\n");
mmc_command_start(MMC_ALL_SEND_CID, 0,MMC_RESP_R2);
if(mmc_command_wait(&card) != MMC_ERR_NONE){
printf("Failed to send MMC_ALL_SEND_CID\n");
return NULL;
}
memcpy((void *) raw_cid, (void *) card.command.resp, sizeof(uint32_t) * 4);
// Set MMC card address
DBG("Set relative address\n");
mmc_command_start(MMC_SET_RELATIVE_ADDR, MMC_DEFAULT_RCA, MMC_RESP_R1);
if(mmc_command_wait(&card) != MMC_ERR_NONE){
printf("Failed to send MMC_SET_RELATIVE_ADDR\n");
return NULL;
}
DBG("Send CSD\n");
mmc_command_start(MMC_SEND_CSD, MMC_DEFAULT_RCA,MMC_RESP_R2);
if(mmc_command_wait(&card) != MMC_ERR_NONE){
printf("Failed to send MMC_SEND_CSD\n");
return NULL;
}
memcpy((void *) raw_csd, (void *) card.command.resp, sizeof(uint32_t) * 4);
// Now we can decode CSD and CID
mmc_decode_csd(&card, raw_csd);
mmc_decode_cid(&card, raw_cid);
// Change clock
DBG("Set clock\n");
omap_mmc_set_clock(card.csd.max_dtr);
// Now lets select the card so
// We can use it.
DBG("Selevt card\n");
mmc_command_start(MMC_SELECT_CARD, MMC_DEFAULT_RCA,MMC_RESP_R1);
if(mmc_command_wait(&card) != MMC_ERR_NONE){
printf("Failed to select card\n");
return NULL;
}
// Lets create new device
mmc_dev = (block_dev_desc_t *) malloc(sizeof(block_dev_desc_t));
// Reset device data
memset((void *) mmc_dev, 0, sizeof(block_dev_desc_t));
mmc_dev->if_type = IF_TYPE_MMC;
mmc_dev->part_type = PART_TYPE_DOS;
mmc_dev->dev = 0;
mmc_dev->lun = 0;
mmc_dev->type = 0;
mmc_dev->lba = (lbaint_t) card.csd.capacity;
mmc_dev->blksz = (1 << card.csd.read_blkbits);
mmc_dev->block_read = omap_mmc_read;
sprintf(mmc_dev->vendor,
"Man %08x Snr %08x",
card.cid.oemid, card.cid.serial);
sprintf(mmc_dev->product,"%s",card.cid.prod_name);
sprintf(mmc_dev->revision,"%x %x",card.cid.hwrev, card.cid.fwrev);
printf("MMC device is configured\n");
fat_register_device(mmc_dev,1); /* partitions start counting with 1 */
return mmc_dev;
}
int mmc_init(int verbose){
return (omap_mmc_init(0) != NULL)? 0 : -ENODEV;
}
int
mmc_ident(block_dev_desc_t *dev)
{
return 0;
}
block_dev_desc_t * mmc_get_dev(int dev)
{
return ((block_dev_desc_t *)mmc_dev);
}
int
mmc2info(ulong addr)
{
#if 0
/* FIXME hard codes to 32 MB device */
if (addr >= CFG_MMC_BASE && addr < CFG_MMC_BASE + 0x02000000) {
return 1;
}
#endif
return 0;
}
int
mmc_write(uchar *src, ulong dst, int size)
{
return 0;
}
int
mmc_read(ulong src, uchar *dst, int size)
{
return 0;
}
#endif
[-- Attachment #3: Type: text/plain, Size: 0 bytes --]
prev parent reply other threads:[~2006-04-03 20:52 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-04-01 12:04 Reading/Writing to MMC without interrupt handler Husam
2006-04-03 14:24 ` Tony Lindgren
2006-04-03 20:52 ` Husam [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200604032152.42890.husamsenussi@gmail.com \
--to=husamsenussi@gmail.com \
--cc=linux-omap-open-source@linux.omap.com \
--cc=tony@atomide.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.