diff --git a/ChangeLog b/ChangeLog index a8c4203b2d5..2105581c9f3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -7171,7 +7171,7 @@ also reset the camera module. Noted by David Sidrane (2014-4-11). * arch/arm/src/stm32/stm32_usbhost.c/.h and stm32_otgfshost.c: USB host tracing added by Leo (2014-4-12). - * arch/arm/src/sama5/sam_adc.c, sam_can.c, sam_emac.c sam_gmac.c: If - running from SDRAM, then BOARD_MCK_FREQUENCY is not a constant and - cannot be used in conditional compilation (2014-4-16). + * arch/arm/src/sama5/sam_adc.c, sam_can.c, sam_emac.c, sam_gmac.c, and + sam_ssc.c: If running from SDRAM, then BOARD_MCK_FREQUENCY is not a + constant and cannot be used in conditional compilation (2014-4-16). diff --git a/arch/arm/src/sama5/Kconfig b/arch/arm/src/sama5/Kconfig index 0cf19458e4f..eea6f0e7c7e 100644 --- a/arch/arm/src/sama5/Kconfig +++ b/arch/arm/src/sama5/Kconfig @@ -268,12 +268,14 @@ config SAMA5_SSC0 default n select I2S depends on SAMA5_DMAC0 + select AUDIO config SAMA5_SSC1 bool "Synchronous Serial Controller 1 (SSC1)" default n select I2S depends on SAMA5_DMAC1 + select AUDIO config SAMA5_CAN0 bool "CAN controller 0 (CAN0)" @@ -300,7 +302,7 @@ config SAMA5_TDES config SAMA5_TRNG bool "True Random Number Generator (TRNG)" default n - select DEV_RANDOM + select ARCH_HAVE_RNG config SAMA5_ARM bool "Performance Monitor Unit (ARM)" diff --git a/arch/arm/src/sama5/sam_ssc.c b/arch/arm/src/sama5/sam_ssc.c index f4fa4d3a445..3024e5ba34f 100644 --- a/arch/arm/src/sama5/sam_ssc.c +++ b/arch/arm/src/sama5/sam_ssc.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/arm/src/sama5/sam_ssc.c * - * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Copyright (C) 2013-2014 Gregory Nutt. All rights reserved. * Authors: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -55,6 +55,7 @@ #include #include #include +#include #include #include "up_internal.h" @@ -102,6 +103,10 @@ # error Invalid value for CONFIG_SAMA5_SSC0_DATALEN #endif +#ifndef CONFIG_AUDIO +# error CONFIG_AUDIO required by this driver +#endif + /* Check if we need to build RX and/or TX support */ #undef SSC_HAVE_RX @@ -117,6 +122,8 @@ # define SSC_HAVE_TX #endif +#if defined(SSC_HAVE_RX) || defined(SSC_HAVE_TX) + /* Check if we need the sample rate to set MCK/2 divider */ #undef SSC_HAVE_MCK2 @@ -161,27 +168,6 @@ #define SCC_PERIOD (SSC_FSLEN + CONFIG_SAMA5_SSC0_DATALEN * SSC_DATNB) /* Clocking *****************************************************************/ -/* Select MCU-specific settings - * - * SSC is driven by the main clock, divided down so that the maximum - * peripheral clocking is not exceeded. - */ - -#if BOARD_MCK_FREQUENCY <= SAM_SSC_MAXPERCLK -# define SSC_FREQUENCY BOARD_MCK_FREQUENCY -# define SSC_PCR_DIV PMC_PCR_DIV1 -#elif (BOARD_MCK_FREQUENCY >> 1) <= SAM_SSC_MAXPERCLK -# define SSC_FREQUENCY (BOARD_MCK_FREQUENCY >> 1) -# define SSC_PCR_DIV PMC_PCR_DIV2 -#elif (BOARD_MCK_FREQUENCY >> 2) <= SAM_SSC_MAXPERCLK -# define SSC_FREQUENCY (BOARD_MCK_FREQUENCY >> 2) -# define SSC_PCR_DIV PMC_PCR_DIV4 -#elif (BOARD_MCK_FREQUENCY >> 3) <= SAM_SSC_MAXPERCLK -# define SSC_FREQUENCY (BOARD_MCK_FREQUENCY >> 3) -# define SSC_PCR_DIV PMC_PCR_DIV8 -#else -# error Cannot realize SSC input frequency -#endif /* Clock source definitions */ @@ -316,6 +302,8 @@ struct sam_ssc_s struct i2s_dev_s dev; /* Externally visible I2S interface */ uintptr_t base; /* SSC controller register base address */ sem_t exclsem; /* Assures mutually exclusive acess to SSC */ + uint8_t datalen; /* Data width (2-32) */ + uint8_t pid; /* Peripheral ID */ uint16_t rxenab:1; /* True: RX transfers enabled */ uint16_t txenab:1; /* True: TX transfers enabled */ uint16_t loopback:1; /* True: Loopback mode */ @@ -324,8 +312,7 @@ struct sam_ssc_s uint16_t txclk:2; /* Transmitter clock source. See SSC_CLKSRC_* definitions */ uint16_t rxout:2; /* Receiver clock output. See SSC_CLKOUT_* definitions */ uint16_t txout:2; /* Transmitter clock output. See SSC_CLKOUT_* definitions */ - uint8_t datalen; /* Data width (2-32) */ - uint8_t pid; /* Peripheral ID */ + uint32_t frequency; /* SSC clock frequency */ #ifdef SSC_HAVE_MCK2 uint32_t samplerate; /* Data sample rate (determines only MCK/2 divider) */ #endif @@ -757,7 +744,7 @@ static void ssc_exclsem_take(struct sam_ssc_s *priv) } /**************************************************************************** - * Name: ssc_exclsem_take + * Name: ssc_bufsem_take * * Description: * Take the buffer semaphore handling any exceptional conditions @@ -1994,9 +1981,11 @@ static int ssc_receive(struct i2s_dev_s *dev, struct ap_buffer_s *apb, i2s_callback_t callback, void *arg, uint32_t timeout) { struct sam_ssc_s *priv = (struct sam_ssc_s *)dev; +#ifdef SSC_HAVE_RX struct sam_buffer_s *bfcontainer; irqstate_t flags; int ret; +#endif DEBUGASSERT(priv && apb && ((uintptr_t)apb->samp & 3) == 0); i2svdbg("apb=%p nmaxbytes=%d arg=%p timeout=%d\n", @@ -2058,6 +2047,7 @@ errout_with_exclsem: #else i2sdbg("ERROR: SSC%d has no receiver\n", priv->sscno); + UNUSED(priv); return -ENOSYS; #endif } @@ -2197,9 +2187,11 @@ static int ssc_send(struct i2s_dev_s *dev, struct ap_buffer_s *apb, i2s_callback_t callback, void *arg, uint32_t timeout) { struct sam_ssc_s *priv = (struct sam_ssc_s *)dev; +#ifdef SSC_HAVE_TX struct sam_buffer_s *bfcontainer; irqstate_t flags; int ret; +#endif DEBUGASSERT(priv && apb && ((uintptr_t)apb->samp & 3) == 0); i2svdbg("apb=%p nbytes=%d arg=%p timeout=%d\n", @@ -2261,6 +2253,7 @@ errout_with_exclsem: #else i2sdbg("ERROR: SSC%d has no transmitter\n", priv->sscno); + UNUSED(priv); return -ENOSYS; #endif } @@ -2598,10 +2591,37 @@ static uint32_t ssc_mck2divider(struct sam_ssc_s *priv) static void ssc_clocking(struct sam_ssc_s *priv) { uint32_t regval; + uint32_t mck; + + /* Determine the maximum SSC peripheral clock frequency */ + + mck = BOARD_MCK_FREQUENCY; + DEBUGASSERT((mck >> 3) <= SAM_SSC_MAXPERCLK); + + if (mck <= SAM_SSC_MAXPERCLK) + { + priv->frequency = mck; + regval = PMC_PCR_DIV1; + } + else if ((mck >> 1) <= SAM_SSC_MAXPERCLK) + { + priv->frequency = (mck >> 1); + regval = PMC_PCR_DIV2; + } + else if ((mck >> 2) <= SAM_SSC_MAXPERCLK) + { + priv->frequency = (mck >> 2); + regval = PMC_PCR_DIV4; + } + else /* if ((mck >> 3) <= SAM_SSC_MAXPERCLK) */ + { + priv->frequency = (mck >> 3); + regval = PMC_PCR_DIV8; + } /* Set the maximum SSC peripheral clock frequency */ - regval = PMC_PCR_PID(priv->pid) | PMC_PCR_CMD | SSC_PCR_DIV | PMC_PCR_EN; + regval |= PMC_PCR_PID(priv->pid) | PMC_PCR_CMD | PMC_PCR_EN; putreg32(regval, SAM_PMC_PCR); /* Reset, disable receiver & transmitter */ @@ -3189,4 +3209,5 @@ errout_with_alloc: return NULL; } +#endif /* SSC_HAVE_RX || SSC_HAVE_TX */ #endif /* CONFIG_SAMA5_SSC0 || CONFIG_SAMA5_SSC1 */