From owner-p4-projects@FreeBSD.ORG Thu Nov 9 00:40:47 2006 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 8B93A16A415; Thu, 9 Nov 2006 00:40:47 +0000 (UTC) X-Original-To: perforce@freebsd.org Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 356F216A40F for ; Thu, 9 Nov 2006 00:40:47 +0000 (UTC) (envelope-from imp@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id F226D43D53 for ; Thu, 9 Nov 2006 00:40:46 +0000 (GMT) (envelope-from imp@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.6/8.13.6) with ESMTP id kA90eke9015453 for ; Thu, 9 Nov 2006 00:40:46 GMT (envelope-from imp@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.6/8.13.4/Submit) id kA90ek9s015450 for perforce@freebsd.org; Thu, 9 Nov 2006 00:40:46 GMT (envelope-from imp@freebsd.org) Date: Thu, 9 Nov 2006 00:40:46 GMT Message-Id: <200611090040.kA90ek9s015450@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to imp@freebsd.org using -f From: Warner Losh To: Perforce Change Reviews Cc: Subject: PERFORCE change 109576 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 09 Nov 2006 00:40:47 -0000 http://perforce.freebsd.org/chv.cgi?CH=109576 Change 109576 by imp@imp_lighthouse on 2006/11/09 00:39:48 Merge mci_device.c into sd-card.c. There wasn't much benefit from having them separate. Remove a few layers of indirection, simplify interfaces, etc. This saves about 650 bytes to boot! Affected files ... .. //depot/projects/arm/src/sys/boot/arm/at91/libat91/mci_device.c#20 delete .. //depot/projects/arm/src/sys/boot/arm/at91/libat91/mci_device.h#11 edit .. //depot/projects/arm/src/sys/boot/arm/at91/libat91/sd-card.c#13 edit Differences ... ==== //depot/projects/arm/src/sys/boot/arm/at91/libat91/mci_device.h#11 (text+ko) ==== @@ -83,43 +83,19 @@ // MMC & SDCard Structures /////////////////////////////////////////////////////////////////////////////// -/*-----------------------------------------------*/ -/* SDCard Device Descriptor Structure Definition */ -/*-----------------------------------------------*/ -typedef struct _AT91S_MciDeviceDesc -{ - volatile unsigned char state; - unsigned char SDCard_bus_width; - -} AT91S_MciDeviceDesc, *AT91PS_MciDeviceDesc; - /*---------------------------------------------*/ -/* MMC & SDCard Structure Device Features */ -/*---------------------------------------------*/ -typedef struct _AT91S_MciDeviceFeatures -{ - unsigned char Card_Inserted; // (0=AT91C_CARD_REMOVED) (1=AT91C_MMC_CARD_INSERTED) (2=AT91C_SD_CARD_INSERTED) - unsigned int Relative_Card_Address; // RCA - unsigned int READ_BL_LEN; - unsigned int WRITE_BL_LEN; - unsigned char Read_Partial; // READ_BL_PARTIAL - unsigned char Write_Partial; // WRITE_BL_PARTIAL - unsigned char Erase_Block_Enable; // ERASE_BLK_EN - unsigned char Read_Block_Misalignment; // READ_BLK_MISALIGN - unsigned char Write_Block_Misalignment; // WRITE_BLK_MISALIGN - unsigned char Sector_Size; // SECTOR_SIZE - unsigned int Memory_Capacity; // Size in bits of the device - -} AT91S_MciDeviceFeatures, *AT91PS_MciDeviceFeatures ; - -/*---------------------------------------------*/ /* MCI Device Structure Definition */ /*---------------------------------------------*/ typedef struct _AT91S_MciDevice { - AT91PS_MciDeviceDesc pMCI_DeviceDesc; // MCI device descriptor - AT91PS_MciDeviceFeatures pMCI_DeviceFeatures;// Pointer on a MCI device features array -} AT91S_MciDevice, *AT91PS_MciDevice; + volatile unsigned char state; + unsigned char SDCard_bus_width; + unsigned int RCA; // RCA + unsigned int READ_BL_LEN; +#ifdef REPORT_SIZE + unsigned int Memory_Capacity; +#endif +} AT91S_MciDevice; #include @@ -450,15 +426,4 @@ #define CSD_0_STRUCT_M 0x03 /////////////////////////////////////////////////////////////////////////////// - -void AT91F_MCI_Device_Handler(AT91PS_MciDevice,unsigned int); -AT91S_MCIDeviceStatus AT91F_MCI_SDCard_Init (AT91PS_MciDevice); -AT91S_MCIDeviceStatus AT91F_MCI_SetBlocklength(unsigned int); -AT91S_MCIDeviceStatus AT91F_MCI_ReadBlock(AT91PS_MciDevice,int,unsigned int *,int); -AT91S_MCIDeviceStatus AT91F_MCI_WriteBlock(AT91PS_MciDevice,int,unsigned int *,int); -#if 0 -AT91S_MCIDeviceStatus AT91F_MCI_MMC_Init (AT91PS_MciDevice pMCI_Device); -AT91S_MCIDeviceStatus AT91F_MCI_MMC_SelectCard(AT91PS_MciDevice pMCI_Device, unsigned int relative_card_address); -#endif - #endif ==== //depot/projects/arm/src/sys/boot/arm/at91/libat91/sd-card.c#13 (text+ko) ==== @@ -51,13 +51,7 @@ #define BUFFER_SIZE_MCI_DEVICE 512 #define MASTER_CLOCK 60000000 -//Private functions -//static void initInts(void); -static void AT91F_MCI_Handler(void); - //* Global Variables -AT91S_MciDeviceFeatures MCI_Device_Features; -AT91S_MciDeviceDesc MCI_Device_Desc; AT91S_MciDevice MCI_Device; char Buffer[BUFFER_SIZE_MCI_DEVICE]; @@ -83,56 +77,126 @@ } while( !(status & AT91C_MCI_NOTBUSY) && (timeout>0) ); - AT91F_MCI_Handler(); + status = AT91C_BASE_MCI->MCI_SR; + + // If End of Tx Buffer Empty interrupt occurred + if (MCI_Device.state == AT91C_MCI_TX_SINGLE_BLOCK && status & AT91C_MCI_TXBUFE) { + AT91C_BASE_MCI->MCI_IDR = AT91C_MCI_TXBUFE; + AT91C_BASE_PDC_MCI->PDC_PTCR = AT91C_PDC_TXTDIS; + MCI_Device.state = AT91C_MCI_IDLE; + } // End of if AT91C_MCI_TXBUFF + + // If End of Rx Buffer Full interrupt occurred + if (MCI_Device.state == AT91C_MCI_RX_SINGLE_BLOCK && status & AT91C_MCI_RXBUFF) { + AT91C_BASE_MCI->MCI_IDR = AT91C_MCI_RXBUFF; + AT91C_BASE_PDC_MCI->PDC_PTCR = AT91C_PDC_RXTDIS; + MCI_Device.state = AT91C_MCI_IDLE; + } // End of if AT91C_MCI_RXBUFF +} + +inline static unsigned int +swap(unsigned int a) +{ + return (((a & 0xff) << 24) | ((a & 0xff00) << 8) | ((a & 0xff0000) >> 8) + | ((a & 0xff000000) >> 24)); } -#if 0 -int -MCI_write (unsigned dest, char* source, unsigned length) +inline static void +wait_ready() { - unsigned sectorLength = 1 << MCI_Device.pMCI_DeviceFeatures->WRITE_BL_LEN; - unsigned offset = dest % sectorLength; - AT91S_MCIDeviceStatus status; - int sizeToWrite; + int status; - //As long as there is data to write - while (length) + // wait for CMDRDY Status flag to read the response + do { - //See if we've got at least a sector to write - if (length > sectorLength) - sizeToWrite = sectorLength; - //Else just write the remainder - else - sizeToWrite = length; + status = AT91C_BASE_MCI->MCI_SR; + } while( !(status & AT91C_MCI_CMDRDY) ); +} + +//*---------------------------------------------------------------------------- +//* \fn AT91F_MCI_SendCommand +//* \brief Generic function to send a command to the MMC or SDCard +//*---------------------------------------------------------------------------- +static int +AT91F_MCI_SendCommand( + unsigned int Cmd, + unsigned int Arg) +{ + unsigned int error; - AT91F_MCIDeviceWaitReady(AT91C_MCI_TIMEOUT); - //Do the writing - status = AT91F_MCI_WriteBlock(&MCI_Device, dest, (unsigned int*)source, sizeToWrite); - //TODO:Status checking + AT91C_BASE_MCI->MCI_ARGR = Arg; + AT91C_BASE_MCI->MCI_CMDR = Cmd; - //Update counters & pointers - length -= sizeToWrite; - dest += sizeToWrite; - source += sizeToWrite; +// printf("CMDR %x ARG %x\n", Cmd, Arg); + wait_ready(); + // Test error ==> if crc error and response R3 ==> don't check error + error = (AT91C_BASE_MCI->MCI_SR) & AT91C_MCI_SR_ERROR; + if (error != 0) { + if (error != AT91C_MCI_RCRCE) + return (1); } + return 0; +} - return 0; +//*---------------------------------------------------------------------------- +//* \fn AT91F_MCI_GetStatus +//* \brief Addressed card sends its status register +//*---------------------------------------------------------------------------- +static unsigned int +AT91F_MCI_GetStatus() +{ + if (AT91F_MCI_SendCommand(SEND_STATUS_CMD, MCI_Device.RCA << 16)) + return AT91C_CMD_SEND_ERROR; + return (AT91C_BASE_MCI->MCI_RSPR[0]); } -#endif -inline static unsigned int -swap(unsigned int a) +//*---------------------------------------------------------------------------- +//* \fn AT91F_MCI_ReadBlock +//* \brief Read an ENTIRE block or PARTIAL block +//*---------------------------------------------------------------------------- +static int +AT91F_MCI_ReadBlock(int src, unsigned int *dataBuffer, int sizeToRead) { - return (((a & 0xff) << 24) | ((a & 0xff00) << 8) | ((a & 0xff0000) >> 8) - | ((a & 0xff000000) >> 24)); + unsigned log2sl = MCI_Device.READ_BL_LEN; + unsigned sectorLength = 1 << log2sl; + + /////////////////////////////////////////////////////////////////////// + if (MCI_Device.state != AT91C_MCI_IDLE) + return 1; + + if ((AT91F_MCI_GetStatus() & AT91C_SR_READY_FOR_DATA) == 0) + return 1; + + /////////////////////////////////////////////////////////////////////// + + // Init Mode Register + AT91C_BASE_MCI->MCI_MR |= ((sectorLength << 16) | AT91C_MCI_PDCMODE); + + sizeToRead = sizeToRead / 4; + + AT91C_BASE_PDC_MCI->PDC_PTCR = (AT91C_PDC_TXTDIS | AT91C_PDC_RXTDIS); + AT91C_BASE_PDC_MCI->PDC_RPR = (unsigned int)dataBuffer; + AT91C_BASE_PDC_MCI->PDC_RCR = sizeToRead; + + // Send the Read single block command + if (AT91F_MCI_SendCommand(READ_SINGLE_BLOCK_CMD, src)) + return AT91C_READ_ERROR; + MCI_Device.state = AT91C_MCI_RX_SINGLE_BLOCK; + + // Enable AT91C_MCI_RXBUFF Interrupt + AT91C_BASE_MCI->MCI_IER = AT91C_MCI_RXBUFF; + + // (PDC) Receiver Transfer Enable + AT91C_BASE_PDC_MCI->PDC_PTCR = AT91C_PDC_RXTEN; + + return 0; } int MCI_read(char* dest, unsigned source, unsigned length) { - unsigned log2sl = MCI_Device.pMCI_DeviceFeatures->READ_BL_LEN; + unsigned log2sl = MCI_Device.READ_BL_LEN; unsigned sectorLength = 1 << log2sl; - AT91S_MCIDeviceStatus status; int sizeToRead; unsigned int *walker; @@ -146,11 +210,8 @@ AT91F_MCIDeviceWaitReady(AT91C_MCI_TIMEOUT); //Do the reading - status = AT91F_MCI_ReadBlock(&MCI_Device, source, - (unsigned int*)dest, sizeToRead); - - //TODO:Status checking - if (status != AT91C_READ_OK) + if (AT91F_MCI_ReadBlock(source, + (unsigned int*)dest, sizeToRead)) return -1; //* Wait MCI Device Ready @@ -179,29 +240,122 @@ { // Init Device Structure - MCI_Device_Features.Relative_Card_Address = 0; - MCI_Device_Features.Card_Inserted = AT91C_SD_CARD_INSERTED; - MCI_Device_Features.READ_BL_LEN = 0; - MCI_Device_Features.WRITE_BL_LEN = 0; - MCI_Device_Features.Read_Partial = 0; - MCI_Device_Features.Write_Partial = 0; - MCI_Device_Features.Erase_Block_Enable = 0; - MCI_Device_Features.Sector_Size = 0; - MCI_Device_Features.Memory_Capacity = 0; - MCI_Device_Desc.state = AT91C_MCI_IDLE; - MCI_Device_Desc.SDCard_bus_width = AT91C_MCI_SCDBUS; - MCI_Device.pMCI_DeviceDesc = &MCI_Device_Desc; - MCI_Device.pMCI_DeviceFeatures = &MCI_Device_Features; + MCI_Device.RCA = 0; + MCI_Device.READ_BL_LEN = 0; +#ifdef REPORT_SIZE + MCI_Device.Memory_Capacity = 0; +#endif + MCI_Device.state = AT91C_MCI_IDLE; + MCI_Device.SDCard_bus_width = AT91C_MCI_SCDBUS; +} + +//*---------------------------------------------------------------------------- +//* \fn AT91F_MCI_SDCard_SendAppCommand +//* \brief Specific function to send a specific command to the SDCard +//*---------------------------------------------------------------------------- +static int +AT91F_MCI_SDCard_SendAppCommand( + unsigned int Cmd_App, + unsigned int Arg) +{ + // Send the CMD55 for application specific command + AT91C_BASE_MCI->MCI_ARGR = (MCI_Device.RCA << 16 ); + AT91C_BASE_MCI->MCI_CMDR = APP_CMD; + + wait_ready(); + // if an error occurs + if (AT91C_BASE_MCI->MCI_SR & AT91C_MCI_SR_ERROR) + return (1); + return (AT91F_MCI_SendCommand(Cmd_App,Arg)); +} + +//*---------------------------------------------------------------------------- +//* \fn AT91F_MCI_GetCSD +//* \brief Asks to the specified card to send its CSD +//*---------------------------------------------------------------------------- +static int +AT91F_MCI_GetCSD(unsigned int rca, unsigned int *response) +{ + + if (AT91F_MCI_SendCommand(SEND_CSD_CMD, (rca << 16))) + return 1; + + response[0] = AT91C_BASE_MCI->MCI_RSPR[0]; + response[1] = AT91C_BASE_MCI->MCI_RSPR[1]; + response[2] = AT91C_BASE_MCI->MCI_RSPR[2]; + response[3] = AT91C_BASE_MCI->MCI_RSPR[3]; + + return 0; +} + +//*---------------------------------------------------------------------------- +//* \fn AT91F_MCI_SDCard_GetOCR +//* \brief Asks to all cards to send their operations conditions +//*---------------------------------------------------------------------------- +static int +AT91F_MCI_SDCard_GetOCR() +{ + unsigned int response=0x0; + + // The RCA to be used for CMD55 in Idle state shall be the card's default RCA=0x0000. + MCI_Device.RCA = 0x0; + + while( (response & AT91C_CARD_POWER_UP_BUSY) != AT91C_CARD_POWER_UP_BUSY ) { + if (AT91F_MCI_SDCard_SendAppCommand(SDCARD_APP_OP_COND_CMD, + AT91C_MMC_HOST_VOLTAGE_RANGE)) + return 1; + response = AT91C_BASE_MCI->MCI_RSPR[0]; + } + return (0); +} + +//*---------------------------------------------------------------------------- +//* \fn AT91F_MCI_SDCard_GetCID +//* \brief Asks to the SDCard on the chosen slot to send its CID +//*---------------------------------------------------------------------------- +static int +AT91F_MCI_SDCard_GetCID(unsigned int *response) +{ + if (AT91F_MCI_SendCommand(ALL_SEND_CID_CMD, AT91C_NO_ARGUMENT)) + return 1; + + response[0] = AT91C_BASE_MCI->MCI_RSPR[0]; + response[1] = AT91C_BASE_MCI->MCI_RSPR[1]; + response[2] = AT91C_BASE_MCI->MCI_RSPR[2]; + response[3] = AT91C_BASE_MCI->MCI_RSPR[3]; + + return 0; } -static void AT91F_MCI_Handler(void) +//*---------------------------------------------------------------------------- +//* \fn AT91F_MCI_SDCard_SetBusWidth +//* \brief Set bus width for SDCard +//*---------------------------------------------------------------------------- +static int +AT91F_MCI_SDCard_SetBusWidth() { - int status; + volatile int ret_value; + char bus_width; + + do { + ret_value=AT91F_MCI_GetStatus(); + } + while((ret_value > 0) && ((ret_value & AT91C_SR_READY_FOR_DATA) == 0)); + + // Select Card + AT91F_MCI_SendCommand(SEL_DESEL_CARD_CMD, (MCI_Device.RCA)<<16); + + // Set bus width for Sdcard + if (MCI_Device.SDCard_bus_width == AT91C_MCI_SCDBUS) + bus_width = AT91C_BUS_WIDTH_4BITS; + else + bus_width = AT91C_BUS_WIDTH_1BIT; -// status = ( AT91C_BASE_MCI->MCI_SR & AT91C_BASE_MCI->MCI_IMR ); - status = AT91C_BASE_MCI->MCI_SR; + if (AT91F_MCI_SDCard_SendAppCommand( + SDCARD_SET_BUS_WIDTH_CMD,bus_width) != AT91C_CMD_SEND_OK) + return 1; - AT91F_MCI_Device_Handler(&MCI_Device, status); + return 0; } //*---------------------------------------------------------------------------- @@ -211,12 +365,12 @@ int sdcard_init(void) { -/////////////////////////////////////////////////////////////////////////////// -// MCI Init : common to MMC and SDCard -/////////////////////////////////////////////////////////////////////////////// + unsigned int tab_response[4]; +#ifdef REPORT_SIZE + unsigned int mult,blocknr; +#endif + int i; - //initInts(); - // Init MCI for MMC and SDCard interface AT91F_MCI_CfgPIO(); AT91F_MCI_CfgPMC(); @@ -229,8 +383,43 @@ AT91C_MCI_DTOR_1MEGA_CYCLES, AT91C_MCI_PDCMODE, AT91C_MCI_SDCARD_4BITS_SLOTA); - - if (AT91F_MCI_SDCard_Init(&MCI_Device) != AT91C_INIT_OK) + AT91F_MCI_SendCommand(GO_IDLE_STATE_CMD, AT91C_NO_ARGUMENT); + + for (i = 0; i < 100; i++) { + if (!AT91F_MCI_SDCard_GetOCR(&MCI_Device)) + break; + printf("."); + } + if (i >= 100) + return 0; + if (AT91F_MCI_SDCard_GetCID(tab_response)) + return 0; + if (AT91F_MCI_SendCommand(SET_RELATIVE_ADDR_CMD, 0)) + return 0; + + MCI_Device.RCA = (AT91C_BASE_MCI->MCI_RSPR[0] >> 16); + if (AT91F_MCI_GetCSD(MCI_Device.RCA,tab_response)) + return 0; + MCI_Device.READ_BL_LEN = (tab_response[1] >> CSD_1_RD_B_LEN_S) & + CSD_1_RD_B_LEN_M; +#ifdef REPORT_SIZE + // compute MULT + mult = 1 << ( ((tab_response[2] >> CSD_2_C_SIZE_M_S) & + CSD_2_C_SIZE_M_M) + 2 ); + // compute MSB of C_SIZE + blocknr = ((tab_response[1] >> CSD_1_CSIZE_H_S) & + CSD_1_CSIZE_H_M) << 2; + // compute MULT * (LSB of C-SIZE + MSB already computed + 1) = BLOCKNR + blocknr = mult * ((blocknr + ((tab_response[2] >> CSD_2_CSIZE_L_S) & + CSD_2_CSIZE_L_M)) + 1); + MCI_Device.Memory_Capacity = (1 << MCI_Device.READ_BL_LEN) * blocknr; +#endif + if (AT91F_MCI_SDCard_SetBusWidth()) + return 0; + if (AT91F_MCI_SendCommand(SET_BLOCKLEN_CMD, 1 << MCI_Device.READ_BL_LEN)) return 0; +#ifdef REPORT_SIZE + printf("Found SD card %u bytes\n", MCI_Device.Memory_Capacity); +#endif return 1; }