spimmc_at91.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2006 by egnite Software GmbH. All rights reserved.
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions
00006  * are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the copyright holders nor the names of
00014  *    contributors may be used to endorse or promote products derived
00015  *    from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
00018  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00019  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00020  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
00021  * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00022  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00023  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00024  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00025  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00026  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00027  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00028  * SUCH DAMAGE.
00029  *
00030  * For additional information see http://www.ethernut.de/
00031  */
00032 
00060 #include <cfg/arch.h>
00061 #include <cfg/arch/gpio.h>
00062 
00063 #include <dev/mmcard.h>
00064 #include <dev/spimmc_at91.h>
00065 
00066 #if 0
00067 /* Use for local debugging. */
00068 #define NUTDEBUG
00069 #include <stdio.h>
00070 #endif
00071 
00076 
00077 #if defined(MCU_AT91SAM9260)
00078 
00079 #ifndef MMC_CS_BIT
00080 #define MMC_CS_BIT      PA3_SPI0_NPCS0_A
00081 #endif
00082 #define MMC_DATAOUT_BIT PA0_SPI0_MISO_A
00083 #define MMC_DATAIN_BIT  PA1_SPI0_MOSI_A
00084 #define MMC_CLK_BIT     PA2_SPI0_SPCK_A
00085 
00086 #elif defined(MCU_AT91SAM7X256)
00087 
00088 #ifndef MMC_CS_BIT
00089 #define MMC_CS_BIT      SPI0_NPCS1_PA13A
00090 #endif
00091 #define MMC_DATAOUT_BIT SPI0_MISO_PA16A
00092 #define MMC_DATAIN_BIT  SPI0_MOSI_PA17A
00093 #define MMC_CLK_BIT     SPI0_SPCK_PA18A
00094 
00095 #elif defined(MCU_AT91SAM7S256) || defined(MCU_AT91SAM7SE512)
00096 
00097 #ifndef MMC_CS_BIT
00098 #define MMC_CS_BIT      SPI0_NPCS0_PA11A
00099 #endif
00100 #define MMC_DATAOUT_BIT SPI0_MISO_PA12A
00101 #define MMC_DATAIN_BIT  SPI0_MOSI_PA13A
00102 #define MMC_CLK_BIT     SPI0_SPCK_PA14A
00103 
00104 #else   /* MCU_AT91SAM7X256 */
00105 #warning "MMC SPI mode not supported on this MCU"
00106 #endif
00107 
00108 #ifndef MMC_PIO_ASR
00109 #define MMC_PIO_ASR     PIOA_ASR
00110 #endif
00111 
00112 #ifndef MMC_PIO_BSR
00113 #define MMC_PIO_BSR     PIOA_BSR
00114 #endif
00115 
00116 #ifndef MMC_PIO_PDR
00117 #define MMC_PIO_PDR     PIOA_PDR
00118 #endif
00119 
00120 #ifndef MMC_PINS_A
00121 #define MMC_PINS_A      (_BV(MMC_DATAOUT_BIT) | _BV(MMC_DATAIN_BIT) | _BV(MMC_CLK_BIT))
00122 #endif
00123 
00124 #ifndef MMC_PINS_B
00125 #define MMC_PINS_B      0
00126 #endif
00127 
00128 #ifndef MMC_CS_PER
00129 #define MMC_CS_PER      PIOA_PER
00130 #endif
00131 
00132 #ifndef MMC_CS_OER
00133 #define MMC_CS_OER      PIOA_OER
00134 #endif
00135 
00136 #ifndef MMC_CS_SODR
00137 #define MMC_CS_SODR     PIOA_SODR
00138 #endif
00139 
00140 #ifndef MMC_CS_CODR
00141 #define MMC_CS_CODR     PIOA_CODR
00142 #endif
00143 
00144 #ifndef MMC_SPI_CR
00145 #define MMC_SPI_CR      SPI0_CR
00146 #endif
00147 
00148 #ifndef MMC_SPI_MR
00149 #define MMC_SPI_MR      SPI0_MR
00150 #endif
00151 
00152 #ifndef MMC_SPI_RDR
00153 #define MMC_SPI_RDR     SPI0_RDR
00154 #endif
00155 
00156 #ifndef MMC_SPI_TDR
00157 #define MMC_SPI_TDR     SPI0_TDR
00158 #endif
00159 
00160 #ifndef MMC_SPI_SR
00161 #define MMC_SPI_SR      SPI0_SR
00162 #endif
00163 
00164 #ifndef MMC_SPI_CSR1
00165 #define MMC_SPI_CSR1    SPI0_CSR1
00166 #endif
00167 
00168 #ifndef MMC_SPI_ID
00169 #define MMC_SPI_ID      SPI0_ID
00170 #endif
00171 
00172 
00181 static int At91SpiMmCard0Init(void)
00182 {
00183     return 0;
00184 }
00185 
00194 static int At91SpiMmCard0Select(int on)
00195 {
00196     int rc = (inr(PIOA_ODSR) & _BV(MMC_CS_BIT)) == 0;
00197 
00198     /* MMC select is low active. */
00199     if (on == 1) {
00200         outr(MMC_CS_CODR, _BV(MMC_CS_BIT));
00201     } else if (on == 0) {
00202         outr(MMC_CS_SODR, _BV(MMC_CS_BIT));
00203     }
00204     return rc;
00205 }
00206 
00214 static u_char At91SpiMmCard0Io(u_char val)
00215 {
00216 #ifdef NUTDEBUG
00217     putchar('[');
00218     if (val != 0xFF) {
00219         printf("s%02X", val);
00220     }
00221 #endif
00222 
00223     /* Transmission is started by writing the transmit data. */
00224     outr(MMC_SPI_TDR, val);
00225     /* Wait for receiver data register full. */
00226     while((inr(MMC_SPI_SR) & SPI_RDRF) == 0);
00227     /* Read data. */
00228     val = (u_char)inr(MMC_SPI_RDR);
00229 
00230 #ifdef NUTDEBUG
00231     if (val != 0xFF) {
00232         printf("r%02X", val);
00233     }
00234     putchar(']');
00235 #endif
00236     return val;
00237 }
00238 
00249 int At91SpiMmCard0Avail(void)
00250 {
00251     return 1;
00252 }
00253 
00261 int At91SpiMmCard0WrProt(void)
00262 {
00263     return 0;
00264 }
00265 
00274 static int At91SpiMmcIfcInit(NUTDEVICE * dev)
00275 {
00276     /* Disable PIO lines used for SPI. */
00277     outr(MMC_PIO_PDR, MMC_PINS_A | MMC_PINS_B);
00278     /* Enable peripherals. */
00279     outr(MMC_PIO_ASR, MMC_PINS_A);
00280     outr(MMC_PIO_BSR, MMC_PINS_B);
00281 
00282     /* MMC chip select is manually controlled. */
00283     outr(MMC_CS_PER, _BV(MMC_CS_BIT));
00284     outr(MMC_CS_SODR, _BV(MMC_CS_BIT));
00285     outr(MMC_CS_OER, _BV(MMC_CS_BIT));
00286 
00287     /* Enable SPI clock. */
00288     outr(PMC_PCER, _BV(MMC_SPI_ID));
00289 
00290     /* SPI enable and reset. */
00291     outr(MMC_SPI_CR, SPI_SPIEN | SPI_SWRST);
00292     outr(MMC_SPI_CR, SPI_SPIEN);
00293 
00294     /* Set SPI to master mode, fixed peripheral at CS1, fault detection disabled. */
00295     outr(MMC_SPI_MR, (1 << SPI_PCS_LSB) | SPI_MODFDIS | SPI_MSTR);
00296 
00297     /* Data changes during clock low and will be sampled on rising edges. */
00298     outr(MMC_SPI_CSR1, (3 << SPI_SCBR_LSB) | SPI_CPOL);
00299 
00300     return MmCardDevInit(dev);
00301 }
00302 
00303 static MMCIFC mmc0_ifc = {
00304     At91SpiMmCard0Init,             
00305     At91SpiMmCard0Io,               
00306     At91SpiMmCard0Select,           
00307     At91SpiMmCard0Avail,            
00308     At91SpiMmCard0WrProt            
00309 };
00310 
00323 NUTDEVICE devAt91SpiMmc0 = {
00324     0,                          
00325     {'M', 'M', 'C', '0', 0, 0, 0, 0, 0}
00326     ,                           
00327     0,                          
00328     0,                          
00329     0,                          
00330     &mmc0_ifc,                  
00331     0,                          
00332     At91SpiMmcIfcInit,          
00333     MmCardIOCtl,                
00334     MmCardBlockRead,            
00335     MmCardBlockWrite,           
00336 #ifdef __HARVARD_ARCH__
00337     MmCardBlockWrite_P,         
00338 #endif
00339     MmCardMount,                
00340     MmCardUnmount,              
00341     0                           
00342 };
00343 

© 2000-2007 by egnite Software GmbH - visit http://www.ethernut.de/