Nut/OS  4.10.3
API Reference
sbi_mmc.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2006 by egnite Software GmbH
00003  * Copyright (C) 2008 by egnite GmbH
00004  *
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions
00009  * are met:
00010  *
00011  * 1. Redistributions of source code must retain the above copyright
00012  *    notice, this list of conditions and the following disclaimer.
00013  * 2. Redistributions in binary form must reproduce the above copyright
00014  *    notice, this list of conditions and the following disclaimer in the
00015  *    documentation and/or other materials provided with the distribution.
00016  * 3. Neither the name of the copyright holders nor the names of
00017  *    contributors may be used to endorse or promote products derived
00018  *    from this software without specific prior written permission.
00019  *
00020  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00021  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00022  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00023  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00024  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00025  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00026  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00027  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00028  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00029  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00030  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00031  * SUCH DAMAGE.
00032  *
00033  * For additional information see http://www.ethernut.de/
00034  */
00035 
00054 
00055 #if defined(MMC_CLK_PIO_BIT) && defined(MMC_CLK_PIO_ID)
00056 #undef GPIO_ID
00057 #define GPIO_ID MMC_CLK_PIO_ID
00058 #include <cfg/arch/porttran.h>
00059 static INLINE void MMC_CLK_LO(void) { GPIO_SET_LO(MMC_CLK_PIO_BIT); }
00060 static INLINE void MMC_CLK_HI(void) { GPIO_SET_HI(MMC_CLK_PIO_BIT); }
00061 static INLINE void MMC_CLK_EN(void) { GPIO_ENABLE(MMC_CLK_PIO_BIT); }
00062 static INLINE void MMC_CLK_SO(void) { GPIO_OUTPUT(MMC_CLK_PIO_BIT); }
00063 #else
00064 #define MMC_CLK_LO()
00065 #define MMC_CLK_HI()
00066 #define MMC_CLK_EN()
00067 #define MMC_CLK_SO()
00068 #endif
00069 
00070 #if defined(MMC_MOSI_PIO_BIT) && defined(MMC_MOSI_PIO_ID)
00071 #undef GPIO_ID
00072 #define GPIO_ID    MMC_MOSI_PIO_ID
00073 #include <cfg/arch/porttran.h>
00074 static INLINE void MMC_MOSI_LO(void) { GPIO_SET_LO(MMC_MOSI_PIO_BIT); }
00075 static INLINE void MMC_MOSI_HI(void) { GPIO_SET_HI(MMC_MOSI_PIO_BIT); }
00076 static INLINE void MMC_MOSI_EN(void) { GPIO_ENABLE(MMC_MOSI_PIO_BIT); }
00077 static INLINE void MMC_MOSI_SO(void) { GPIO_OUTPUT(MMC_MOSI_PIO_BIT); }
00078 #else
00079 #define MMC_MOSI_LO()
00080 #define MMC_MOSI_HI()
00081 #define MMC_MOSI_EN()
00082 #define MMC_MOSI_SO()
00083 #endif
00084 
00085 #if defined(MMC_MISO_PIO_BIT) && defined(MMC_MISO_PIO_ID)
00086 #undef GPIO_ID
00087 #define GPIO_ID    MMC_MISO_PIO_ID
00088 #include <cfg/arch/porttran.h>
00089 static INLINE int MMC_MISO_TEST(void) { return GPIO_GET(MMC_MISO_PIO_BIT); }
00090 static INLINE void MMC_MISO_EN(void) { GPIO_ENABLE(MMC_MISO_PIO_BIT); }
00091 static INLINE void MMC_MISO_SI(void) { GPIO_INPUT(MMC_MISO_PIO_BIT); }
00092 #else
00093 #define MMC_MISO_TEST() (1)
00094 #define MMC_MISO_EN()
00095 #define MMC_MISO_SI()
00096 #endif
00097 
00098 #if defined(MMC_CS_PIO_BIT) && defined(MMC_CS_PIO_ID)
00099 #undef GPIO_ID
00100 #define GPIO_ID    MMC_CS_PIO_ID
00101 #include <cfg/arch/porttran.h>
00102 static INLINE void MMC_CS_LO(void) { GPIO_SET_LO(MMC_CS_PIO_BIT); }
00103 static INLINE void MMC_CS_HI(void) { GPIO_SET_HI(MMC_CS_PIO_BIT); }
00104 static INLINE int MMC_CS_IS(void) { return GPIO_IS_HI(MMC_CS_PIO_BIT); }
00105 static INLINE void MMC_CS_EN(void) { GPIO_ENABLE(MMC_CS_PIO_BIT); }
00106 static INLINE void MMC_CS_SO(void) { GPIO_OUTPUT(MMC_CS_PIO_BIT); }
00107 #else
00108 #define MMC_CS_LO()
00109 #define MMC_CS_HI()
00110 #define MMC_CS_IS()    (1)
00111 #define MMC_CS_EN()
00112 #define MMC_CS_SO()
00113 #endif
00114 
00115 
00119 typedef struct _MMCDCB {
00120     int dcb_avail;              
00121     int dcb_changed;            
00122 } MMCDCB;
00123 
00124 static MMCDCB mmc_dcb;
00125 
00134 static int SbiMmCardInit(void)
00135 {
00136     mmc_dcb.dcb_changed = 0;
00137     if (mmc_dcb.dcb_avail) {
00138         return 0;
00139     }
00140     return -1;
00141 }
00142 
00151 static int SbiMmCardSelect(int on)
00152 {
00153     int rc = MMC_CS_IS();
00154 
00155     /* MMC select is low active. */
00156     if (on == 1) {
00157         MMC_CS_LO();
00158     } else if (on == 0) {
00159         MMC_CS_HI();
00160     }
00161     return rc;
00162 }
00163 
00171 static uint8_t SbiMmCardIo(uint8_t val)
00172 {
00173     uint_fast8_t msk = 0x80;
00174 
00175 #if defined(NUTDEBUG)
00176     putchar('[');
00177     if (val != 0xFF) {
00178         printf("s%02X", val);
00179     }
00180 #endif
00181 
00182     /* SPI bit banging. */
00183     while (msk) {
00184         MMC_CLK_LO();
00185         if (val & msk) {
00186             MMC_MOSI_HI();
00187         } else {
00188             MMC_MOSI_LO();
00189         }
00190         _NOP(); _NOP(); _NOP(); _NOP();
00191         _NOP(); _NOP(); _NOP(); _NOP();
00192         _NOP(); _NOP(); _NOP(); _NOP();
00193         _NOP(); _NOP(); _NOP(); _NOP();
00194         MMC_CLK_HI();
00195         if (MMC_MISO_TEST()) {
00196             val |= msk;
00197         }
00198         else {
00199             val &= ~msk;
00200         }
00201         msk >>= 1;
00202     }
00203 
00204 #if defined(NUTDEBUG)
00205     if (val != 0xFF) {
00206         printf("r%02X", val);
00207     }
00208     putchar(']');
00209 #endif
00210     return val;
00211 }
00212 
00223 static int SbiMmCardAvail(void)
00224 {
00225     if (mmc_dcb.dcb_avail) {
00226         if (mmc_dcb.dcb_changed) {
00227             return 2;
00228         }
00229         return 1;
00230     }
00231     return 0;
00232 }
00233 
00241 static int SbiMmCardWrProt(void)
00242 {
00243     return 0;
00244 }
00245 
00254 static int SbiMmcIfcInit(NUTDEVICE * dev)
00255 {
00256     /* Enable all clocks. */
00257 #if defined(PMC_PCER)
00258 #if defined(MMC_CLK_PIO_ID)
00259     outr(PMC_PCER, _BV(MMC_CLK_PIO_ID));
00260 #endif
00261 #if defined(MMC_MOSI_PIO_ID)
00262     outr(PMC_PCER, _BV(MMC_MOSI_PIO_ID));
00263 #endif
00264 #if defined(MMC_MISO_PIO_ID)
00265     outr(PMC_PCER, _BV(MMC_MISO_PIO_ID));
00266 #endif
00267 #if defined(MMC_CS_PIO_ID)
00268     outr(PMC_PCER, _BV(MMC_CS_PIO_ID));
00269 #endif
00270 #if defined(MMC_CD_PIO_ID)
00271     outr(PMC_PCER, _BV(MMC_CD_PIO_ID));
00272 #endif
00273 #if defined(MMC_WP_PIO_ID)
00274     outr(PMC_PCER, _BV(MMC_WP_PIO_ID));
00275 #endif
00276 #endif /* PMC_PCER */
00277 
00278     /* Set all outputs high. */
00279     MMC_CLK_HI();
00280     MMC_MOSI_HI();
00281     MMC_CS_HI();
00282 
00283     /* Enable GPIO on all lines. */
00284     MMC_CLK_EN();
00285     MMC_MOSI_EN();
00286     MMC_MISO_EN();
00287     MMC_CS_EN();
00288 
00289     /* Set line directions. */
00290     MMC_CLK_SO();
00291     MMC_MOSI_SO();
00292     MMC_MISO_SI();
00293     MMC_CS_SO();
00294 
00295     mmc_dcb.dcb_avail = 1;
00296     mmc_dcb.dcb_changed = 0;
00297 
00298     return MmCardDevInit(dev);
00299 }
00300 
00301 static MMCIFC mmc_ifc = {
00302     SbiMmCardInit,             
00303     SbiMmCardIo,               
00304     SbiMmCardSelect,           
00305     SbiMmCardAvail,            
00306     SbiMmCardWrProt            
00307 };
00308 
00321 NUTDEVICE devSbiMmCard = {
00322     0,                  
00323     MMC_DEV_NAME,       
00324     0,                  
00325     0,                  
00326     0,                  
00327     &mmc_ifc,           
00328     &mmc_dcb,           
00329     SbiMmcIfcInit,      
00330     MmCardIOCtl,        
00331     MmCardBlockRead,    
00332     MmCardBlockWrite,   
00333 #ifdef __HARVARD_ARCH__
00334     MmCardBlockWrite_P, 
00335 #endif
00336     MmCardMount,        
00337     MmCardUnmount,      
00338     0                   
00339 };
00340