All of lore.kernel.org
 help / color / mirror / Atom feed
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 --]



      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.