diff --git a/configs/freedom-k64f/src/k64_automount.c b/configs/freedom-k64f/src/k64_automount.c new file mode 100644 index 00000000000..4862d55dad4 --- /dev/null +++ b/configs/freedom-k64f/src/k64_automount.c @@ -0,0 +1,327 @@ +/************************************************************************************ + * configs/freedom-k64f/src/k64_automount.c + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#if defined(CONFIG_FS_AUTOMOUNTER_DEBUG) && !defined(CONFIG_DEBUG_FS) +# define CONFIG_DEBUG_FS 1 +#endif + +#include + +#include +#include +#include + +#include "freedom-k64f.h" + +#ifdef HAVE_AUTOMOUNTER + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +#ifndef NULL +# define NULL (FAR void *)0 +#endif + +#ifndef OK +# define OK 0 +#endif + +/************************************************************************************ + * Private Types + ************************************************************************************/ +/* This structure represents the changeable state of the automounter */ + +struct k64_automount_state_s +{ + volatile automount_handler_t handler; /* Upper half handler */ + FAR void *arg; /* Handler argument */ + bool enable; /* Fake interrupt enable */ + bool pending; /* Set if there an event while disabled */ +}; + +/* This structure represents the static configuration of an automounter */ + +struct k64_automount_config_s +{ + /* This must be first thing in structure so that we can simply cast from struct + * automount_lower_s to struct k64_automount_config_s + */ + + struct automount_lower_s lower; /* Publicly visible part */ + FAR struct k64_automount_state_s *state; /* Changeable state */ +}; + +/************************************************************************************ + * Private Function Prototypes + ************************************************************************************/ + +static int k64_attach(FAR const struct automount_lower_s *lower, + automount_handler_t isr, FAR void *arg); +static void k64_enable(FAR const struct automount_lower_s *lower, bool enable); +static bool k64_inserted(FAR const struct automount_lower_s *lower); + +/************************************************************************************ + * Private Data + ************************************************************************************/ + +static struct k64_automount_state_s g_sdhc_state; +static const struct k64_automount_config_s g_sdhc_config = +{ + .lower = + { + .fstype = CONFIG_FRDMK64F_SDHC_AUTOMOUNT_FSTYPE, + .blockdev = CONFIG_FRDMK64F_SDHC_AUTOMOUNT_BLKDEV, + .mountpoint = CONFIG_FRDMK64F_SDHC_AUTOMOUNT_MOUNTPOINT, + .ddelay = MSEC2TICK(CONFIG_FRDMK64F_SDHC_AUTOMOUNT_DDELAY), + .udelay = MSEC2TICK(CONFIG_FRDMK64F_SDHC_AUTOMOUNT_UDELAY), + .attach = k64_attach, + .enable = k64_enable, + .inserted = k64_inserted + }, + .state = &g_sdhc_state +}; + +/************************************************************************************ + * Private Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: k64_attach + * + * Description: + * Attach a new SDHC event handler + * + * Input Parameters: + * lower - An instance of the auto-mounter lower half state structure + * isr - The new event handler to be attach + * arg - Client data to be provided when the event handler is invoked. + * + * Returned Value: + * Always returns OK + * + ************************************************************************************/ + +static int k64_attach(FAR const struct automount_lower_s *lower, + automount_handler_t isr, FAR void *arg) +{ + FAR const struct k64_automount_config_s *config; + FAR struct k64_automount_state_s *state; + + /* Recover references to our structure */ + + config = (FAR struct k64_automount_config_s *)lower; + DEBUGASSERT(config && config->state); + + state = config->state; + + /* Save the new handler info (clearing the handler first to eliminate race + * conditions). + */ + + state->handler = NULL; + state->pending = false; + state->arg = arg; + state->handler = isr; + return OK; +} + +/************************************************************************************ + * Name: k64_enable + * + * Description: + * Enable card insertion/removal event detection + * + * Input Parameters: + * lower - An instance of the auto-mounter lower half state structure + * enable - True: enable event detection; False: disable + * + * Returned Value: + * None + * + ************************************************************************************/ + +static void k64_enable(FAR const struct automount_lower_s *lower, bool enable) +{ + FAR const struct k64_automount_config_s *config; + FAR struct k64_automount_state_s *state; + irqstate_t flags; + + /* Recover references to our structure */ + + config = (FAR struct k64_automount_config_s *)lower; + DEBUGASSERT(config && config->state); + + state = config->state; + + /* Save the fake enable setting */ + + flags = enter_critical_section(); + state->enable = enable; + + /* Did an interrupt occur while interrupts were disabled? */ + + if (enable && state->pending) + { + /* Yes.. perform the fake interrupt if the interrutp is attached */ + + if (state->handler) + { + bool inserted = k64_cardinserted(); + (void)state->handler(&config->lower, state->arg, inserted); + } + + state->pending = false; + } + + leave_critical_section(flags); +} + +/************************************************************************************ + * Name: k64_inserted + * + * Description: + * Check if a card is inserted into the slot. + * + * Input Parameters: + * lower - An instance of the auto-mounter lower half state structure + * + * Returned Value: + * True if the card is inserted; False otherwise + * + ************************************************************************************/ + +static bool k64_inserted(FAR const struct automount_lower_s *lower) +{ + FAR const struct k64_automount_config_s *config; + + config = (FAR struct k64_automount_config_s *)lower; + DEBUGASSERT(config && config->state); + + return k64_cardinserted(); +} + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: k64_automount_initialize + * + * Description: + * Configure auto-mounters for each enable and so configured SDHC + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ************************************************************************************/ + +void k64_automount_initialize(void) +{ + FAR void *handle; + + finfo("Initializing automounter(s)\n"); + + /* Initialize the SDHC0 auto-mounter */ + + handle = automount_initialize(&g_sdhc_config.lower); + if (!handle) + { + ferr("ERROR: Failed to initialize auto-mounter for SDHC0\n"); + } +} + +/************************************************************************************ + * Name: k64_automount_event + * + * Description: + * The SDHC card detection logic has detected an insertion or removal event. It + * has already scheduled the MMC/SD block driver operations. Now we need to + * schedule the auto-mount event which will occur with a substantial delay to make + * sure that everything has settle down. + * + * Input Parameters: + * slotno - Identifies the SDHC0 slot: SDHC0_SLOTNO or SDHC1_SLOTNO. There is a + * terminology problem here: Each SDHC supports two slots, slot A and slot B. + * Only slot A is used. So this is not a really a slot, but an HSCMI peripheral + * number. + * inserted - True if the card is inserted in the slot. False otherwise. + * + * Returned Value: + * None + * + * Assumptions: + * Interrupts are disabled. + * + ************************************************************************************/ + +void k64_automount_event(bool inserted) +{ + FAR const struct k64_automount_config_s *config = &g_sdhc_config; + FAR struct k64_automount_state_s *state = &g_sdhc_state; + + /* Is the auto-mounter interrupt attached? */ + + if (state->handler) + { + /* Yes.. Have we been asked to hold off interrupts? */ + + if (!state->enable) + { + /* Yes.. just remember the there is a pending interrupt. We will + * deliver the interrupt when interrupts are "re-enabled." + */ + + state->pending = true; + } + else + { + /* No.. forward the event to the handler */ + + (void)state->handler(&config->lower, state->arg, inserted); + } + } +} + +#endif /* HAVE_AUTOMOUNTER */ diff --git a/configs/freedom-k64f/src/k64_sdhc.c b/configs/freedom-k64f/src/k64_sdhc.c new file mode 100644 index 00000000000..7c33abddaaf --- /dev/null +++ b/configs/freedom-k64f/src/k64_sdhc.c @@ -0,0 +1,239 @@ +/**************************************************************************** + * config/freedom-k64f/src/k64_sdhc.c + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* A micro Secure Digital (SD) card slot is available on the FRDM-K64F connected to + * the SD Host Controller (SDHC) signals of the MCU. This slot will accept micro + * format SD memory cards. The SD card detect pin (PTE6) is an open switch that + * shorts with VDD when card is inserted. + * + * ------------ ------------- -------- + * SD Card Slot Board Signal K64F Pin + * ------------ ------------- -------- + * DAT0 SDHC0_D0 PTE0 + * DAT1 SDHC0_D1 PTE1 + * DAT2 SDHC0_D2 PTE5 + * CD/DAT3 SDHC0_D3 PTE4 + * CMD SDHC0_CMD PTE3 + * CLK SDHC0_DCLK PTE2 + * SWITCH D_CARD_DETECT PTE6 + * ------------ ------------- -------- + * + * There is no Write Protect pin available to the K64F. + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +#include "kinetis.h" + +#include "freedom-k64f.h" + +#ifdef HAVE_MMCSD + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ +/* This structure holds static information unique to one SDHC peripheral */ + +struct k64_sdhc_state_s +{ + struct sdio_dev_s *sdhc; /* R/W device handle */ + bool inserted; /* TRUE: card is inserted */ +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* HSCMI device state */ + +static struct k64_sdhc_state_s g_sdhc; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: k64_mediachange + ****************************************************************************/ + +static void k64_mediachange(void) +{ + bool inserted; + + /* Get the current value of the card detect pin. This pin is pulled up on + * board. So low means that a card is present. + */ + + inserted = !kinetis_gpioread(GPIO_SD_CARDDETECT); + + /* Has the pin changed state? */ + + if (inserted != g_sdhc.inserted) + { + /* Yes.. perform the appropriate action (this might need some debounce). */ + + g_sdhc.inserted = inserted; + sdhc_mediachange(g_sdhc.sdhc, inserted); + +#ifdef CONFIG_FRDMK64F_SDHC_AUTOMOUNT + /* Let the automounter know about the insertion event */ + + k64_automount_event(SDHC0_SLOTNO, k64_cardinserted()); +#endif + } +} + +/**************************************************************************** + * Name: k64_cdinterrupt + ****************************************************************************/ + +static int k64_cdinterrupt(int irq, FAR void *context) +{ + /* All of the work is done by k64_mediachange() */ + + k64_mediachange(); + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: k64_sdhc_initialize + * + * Description: + * Inititialize the SDHC SD card slot + * + ****************************************************************************/ + +int k64_sdhc_initialize(void) +{ + struct k64_sdhc_state_s *state = &g_sdhc; + int ret; + + /* Configure GPIO pins */ + + /* Attached the card detect interrupt (but don't enable it yet) */ + + kinetis_pinconfig(GPIO_SD_CARDDETECT); + kinetis_pinirqattach(GPIO_SD_CARDDETECT, k64_cdinterrupt); + + /* Configure the write protect GPIO -- None */ + + /* Mount the SDHC-based MMC/SD block driver */ + /* First, get an instance of the SDHC interface */ + + mcinfo("Initializing SDHC slot %d\n", MMCSD_SLOTNO); + + g_sdhc.sdhc = sdhc_initialize(MMCSD_SLOTNO); + if (!g_sdhc.sdhc) + { + mcerr("ERROR: Failed to initialize SDHC slot %d\n", MMCSD_SLOTNO); + return -ENODEV; + } + + /* Now bind the SDHC interface to the MMC/SD driver */ + + mcinfo("Bind SDHC to the MMC/SD driver, minor=%d\n", MMSCD_MINOR); + + ret = mmcsd_slotinitialize(MMSCD_MINOR, g_sdhc.sdhc); + if (ret != OK) + { + syslog(LOG_ERR, "ERROR: Failed to bind SDHC to the MMC/SD driver: %d\n", ret); + return ret; + } + + syslog(LOG_INFO, "Successfully bound SDHC to the MMC/SD driver\n"); + + /* Handle the initial card state */ + + k64_mediachange(); + + /* Enable CD interrupts to handle subsequent media changes */ + + kinetis_pinirqenable(GPIO_SD_CARDDETECT); + return OK; +} + +/**************************************************************************** + * Name: k64_cardinserted + * + * Description: + * Check if a card is inserted into the SDHC slot + * + ****************************************************************************/ + +#ifdef HAVE_AUTOMOUNTER +bool k64_cardinserted(void) +{ + return !kinetis_gpioread(GPIO_SD_CARDDETECT); +} +#endif + +/**************************************************************************** + * Name: k64_writeprotected + * + * Description: + * Check if a card is inserted into the SDHC slot + * + ****************************************************************************/ + +#ifdef HAVE_AUTOMOUNTER +bool k64_writeprotected(void) +{ + /* There are no write protect pins */ + + return false; +} +#endif + +#endif /* HAVE_MMCSD */