PERFORCE change 109576 for review
Warner Losh
imp at FreeBSD.org
Thu Nov 9 00:40:47 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=109576
Change 109576 by imp at 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 <dev/mmc/mmcreg.h>
@@ -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;
}
More information about the p4-projects
mailing list