Nut/OS  4.10.3
API Reference
spi_mmc_gpio.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2011 by Thermotemp GmbH
00003  *
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  *
00010  * 1. Redistributions of source code must retain the above copyright
00011  *    notice, this list of conditions and the following disclaimer.
00012  * 2. Redistributions in binary form must reproduce the above copyright
00013  *    notice, this list of conditions and the following disclaimer in the
00014  *    documentation and/or other materials provided with the distribution.
00015  * 3. Neither the name of the copyright holders nor the names of
00016  *    contributors may be used to endorse or promote products derived
00017  *    from this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00020  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00021  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00022  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00023  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00024  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00025  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00026  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00027  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00028  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00029  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00030  * SUCH DAMAGE.
00031  *
00032  * For additional information see http://www.ethernut.de/
00033  */
00034 
00047 #include <cfg/clock.h>
00048 #include <cfg/mmci.h>
00049 
00050 #include <dev/mmcard.h>
00051 #include <dev/spibus.h>
00052 #include <dev/gpio.h>
00053 
00054 #ifdef MMC_CD_PORT
00055     #if (MMC_CD_PORT==NUTGPIO_PORTA)
00056         #define MMC_CD_SIGNAL  sig_GPIO1
00057     #elif (MMC_CD_PORT==NUTGPIO_PORTB)
00058         #define MMC_CD_SIGNAL  sig_GPIO2
00059     #elif (MMC_CD_PORT==NUTGPIO_PORTC)
00060         #define MMC_CD_SIGNAL  sig_GPIO3
00061     #endif
00062 #endif
00063 
00064 #if !defined(SPI_MMC_CLK)
00065 #define SPI_MMC_CLK   33000000
00066 #endif
00067 
00068 #if !defined(SPI_MMC_CS)
00069 #define SPI_MMC_CS    1
00070 #endif
00071 
00072 
00078 
00079 static int  SpiMmcGpioReset(NUTDEVICE * dev);
00080 static void SpiMmcGpioLed(int mode);
00081 static int  SpiMmcGpioPower(int mode);
00082 
00086 static MEMCARDSUPP mcsSpiMmcGpio = {
00087     0,                  
00088     0,                  
00089     SpiMmcGpioReset,    
00090     SpiMmcGpioLed,      
00091     SpiMmcGpioPower,    
00092 };
00093 
00094 #if defined(MMC_CD_PORT) && defined(MMC_CD_PIN)
00095 
00100 static void SpiMmcGpioIrq(void *arg)
00101 {
00102     MEMCARDSUPP *mcs = (MEMCARDSUPP *) arg;
00103 
00104     if (GpioPinGet(MMC_CD_PORT, MMC_CD_PIN) == 0) {
00105         /* Card was inserted */
00106 
00107         /* Set the change flag. */
00108         mcs->mcs_cf = 1;
00109         /* Set the card detect flag. */
00110         mcs->mcs_sf = NUTMC_SF_CD; 
00111 
00112 #if defined(MMC_WP_PORT) && defined(MMC_WP_PIN)
00113         if (GpioPinGet(MMC_WP_PORT, MMC_WP_PIN) == 0) {
00114             mcs->mcs_sf |= NUTMC_SF_WP
00115         }
00116 #endif
00117     } else {
00118         /* Card was removed */
00119 
00120         /* Set the change flag. */
00121         mcs->mcs_cf = 1;
00122         /* Clear card detect and write protect flags. */
00123         mcs->mcs_sf = 0;
00124     }
00125 }
00126 #endif
00127 
00135 static void SpiMmcGpioLed(int mode)
00136 {
00137     if (mode == NUTMC_IND_OFF) {
00138         // switch off LED
00139     } else {
00140         // switch on LED
00141     }
00142 }
00143 
00154 static int SpiMmcGpioPower(int mode)
00155 {
00156     return -1;
00157 }
00158 
00164 static int SpiMmcGpioReset(NUTDEVICE * dev)
00165 {
00166     NUTSPINODE * node;
00167     NUTSPIBUS  * bus;
00168 
00169     int rc;
00170     
00171     node = (NUTSPINODE *) dev->dev_icb;
00172     bus = (NUTSPIBUS *) node->node_bus;
00173     
00174     /*
00175      * 80 bits of ones with deactivated chip select will put the card 
00176      * in SPI mode.
00177      */
00178     node->node_mode |= SPI_MODE_CSHIGH;
00179     rc = (bus->bus_alloc) (node, 1000);
00180     if (rc == 0) {       
00181         uint8_t txb[10] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
00182         (bus->bus_transfer) (node, &txb, NULL, 10);
00183     }
00184     node->node_mode &= ~SPI_MODE_CSHIGH;
00185     (bus->bus_release) (node);
00186 
00187     /* Switch LED off. */
00188     SpiMmcGpioLed(NUTMC_IND_OFF);
00189 
00190     return 0;
00191 }
00192 
00201 static int SpiMmcGpioInit(NUTDEVICE * dev)
00202 {
00203     int rc;
00204 
00205     SpiMmcGpioReset(dev);
00206 
00207 #if defined(MMC_WP_PORT) && defined(MMC_WP_PIN)
00208     /* Configure write protect detection pin as input with pullups enabled */
00209     GpioPinConfigSet(MMC_WP_PORT, MMC_WP_PIN, GPIO_CFG_PULLUP);
00210 #endif    
00211     
00212 #if defined(MMC_CD_PORT) && defined(MMC_CD_PIN)
00213     /* Configure card detect pin as input with pullups enabled */
00214     GpioPinConfigSet(MMC_CD_PORT, MMC_CD_PIN, GPIO_CFG_PULLUP);
00215 
00216     /* Register card detection interrupt. */
00217    
00218     rc = GpioRegisterIrqHandler(&MMC_CD_SIGNAL, MMC_CD_PIN, SpiMmcGpioIrq, dev->dev_dcb);
00219     if (rc == 0) {
00220         GpioIrqEnable(&MMC_CD_SIGNAL, MMC_CD_PIN);
00221         /* Initialize the SPI interface. */
00222         rc = SpiMmcInit(dev);
00223     }
00224     /* call the IRQ handler routine to check if a card is available just right now */
00225     SpiMmcGpioIrq(dev->dev_dcb);
00226 #else
00227     /* No card detect pin is defined, so we assume that the card is always present */
00228     rc = SpiMmcInit(dev);
00229 
00230     /* Set the change flag. */
00231     ((MEMCARDSUPP *)dev->dev_dcb)->mcs_cf = 1;
00232     /* Set the card detect flag. */
00233     ((MEMCARDSUPP *)dev->dev_dcb)->mcs_sf = NUTMC_SF_CD; 
00234 
00235 #if defined(MMC_WP_PORT) && defined(MMC_WP_PIN)
00236     if (GpioPinGet(MMC_WP_PORT, MMC_WP_PIN) == 0) {
00237         ((MEMCARDSUPP *)dev->dev_dcb)->mcs_sf |= NUTMC_SF_WP
00238     }
00239 #endif
00240     
00241 #endif
00242     return rc;
00243 }
00244 
00248 NUTSPINODE nodeSpiMmcGpio = {
00249     NULL,           
00250     NULL,           
00251     SPI_MMC_CLK,    
00252     SPI_MODE_0,     
00253     8,              
00254     SPI_MMC_CS      
00255 };
00256 
00269 NUTDEVICE devSpiMmcGpio = {
00270     0,                  
00271     {'M', 'M', 'C', '0', 0, 0, 0, 0, 0}
00272     ,                   
00273     0,                  
00274     0,                  
00275     0,                  
00276     &nodeSpiMmcGpio,    
00277     &mcsSpiMmcGpio,     
00278     SpiMmcGpioInit,     
00279     SpiMmcIOCtl,        
00280     SpiMmcBlockRead,    
00281     SpiMmcBlockWrite,   
00282 #ifdef __HARVARD_ARCH__
00283     SpiMmcBlockWrite_P, 
00284 #endif
00285     SpiMmcMount,        
00286     SpiMmcUnmount,      
00287     0                   
00288 };
00289