diff --git a/arch/arm/src/samv7/Kconfig b/arch/arm/src/samv7/Kconfig index 0e50a701e14..54bafb2b818 100644 --- a/arch/arm/src/samv7/Kconfig +++ b/arch/arm/src/samv7/Kconfig @@ -738,6 +738,12 @@ endchoice # SPI1 Configuration if SAMV7_SPI_MASTER comment "SPI Master Configuration" +config SAMV7_SPI_CS_DECODING + bool "SPI Peripheral Chip Select Decoding" + default n + ---help--- + Use Peripheral Chip Select Decoding on SPI Master + config SAMV7_SPI_DMA bool "SPI DMA" default n diff --git a/arch/arm/src/samv7/sam_spi.c b/arch/arm/src/samv7/sam_spi.c index 6862577b7f1..0d9f1ec32a1 100644 --- a/arch/arm/src/samv7/sam_spi.c +++ b/arch/arm/src/samv7/sam_spi.c @@ -297,13 +297,24 @@ static void spi_recvblock(struct spi_dev_s *dev, void *buffer, * Private Data ****************************************************************************/ -/* This array maps chip select numbers (0-3) to CSR register offsets */ +/* This array maps chip select numbers (0-3 or 1-15) to CSR register offsets */ +#if defined(CONFIG_SAMV7_SPI_CS_DECODING) +static const uint8_t g_csroffset[16] = +{ + 0, /* the CS counts from 1 to 15 */ + SAM_SPI_CSR0_OFFSET, SAM_SPI_CSR0_OFFSET, SAM_SPI_CSR0_OFFSET, SAM_SPI_CSR0_OFFSET, + SAM_SPI_CSR1_OFFSET, SAM_SPI_CSR1_OFFSET, SAM_SPI_CSR1_OFFSET, SAM_SPI_CSR1_OFFSET, + SAM_SPI_CSR2_OFFSET, SAM_SPI_CSR2_OFFSET, SAM_SPI_CSR2_OFFSET, SAM_SPI_CSR2_OFFSET, + SAM_SPI_CSR3_OFFSET, SAM_SPI_CSR3_OFFSET, SAM_SPI_CSR3_OFFSET +}; +#else static const uint8_t g_csroffset[4] = { SAM_SPI_CSR0_OFFSET, SAM_SPI_CSR1_OFFSET, SAM_SPI_CSR2_OFFSET, SAM_SPI_CSR3_OFFSET }; +#endif #ifdef CONFIG_SAMV7_SPI0_MASTER /* SPI0 driver operations */ @@ -581,7 +592,11 @@ static inline void spi_flush(struct sam_spidev_s *spi) * registers. A chip select number is used for indexing and identifying * chip selects. However, the chip select information is represented by * a bit set in the SPI registers. This function maps those chip select - * numbers to the correct bit set: + * numbers to the correct bit set. + * + * The SAMx7 Processors can handle the chip selects in two different modes. + * The first and default mode assigns one of the four chip select pins + * to one hardware slave. In this mode the function behaviors like: * * CS Returned Spec Effective * No. PCS Value NPCS @@ -591,17 +606,28 @@ static inline void spi_flush(struct sam_spidev_s *spi) * 2 0011 x011 1011 * 3 0111 0111 0111 * + * The second mode, activated via CONFIG_SAMV7_SPI_CS_DECODING uses the four + * chip select pins in "encoded mode" which means, that up to 15 slaves can + * be selected via an additional multiplex electronic to decode the values + * represented by the four lines. In that mode this function returns the + * Bitmask the chip select number represents itself. + * * Input Parameters: * spics - Device-specific state data * * Returned Value: - * None + * Bitmask the pcs part of the SPI data transfer register should be switched + * to for the chip select used. * ****************************************************************************/ static inline uint32_t spi_cs2pcs(struct sam_spics_s *spics) { +#ifndef CONFIG_SAMV7_SPI_CS_DECODING return ((uint32_t)1 << (spics->cs)) - 1; +#else + return spics->cs; +#endif } /**************************************************************************** @@ -1855,7 +1881,14 @@ FAR struct spi_dev_s *sam_spibus_initialize(int port) /* Configure the SPI mode register */ +#if defined(CONFIG_SAMV7_SPI_CS_DECODING) + /* Enable Peripheral Chip Select Decoding? */ + + spi_putreg(spi, SPI_MR_MSTR | SPI_MR_MODFDIS | SPI_MR_PCSDEC, + SAM_SPI_MR_OFFSET); +#else spi_putreg(spi, SPI_MR_MSTR | SPI_MR_MODFDIS, SAM_SPI_MR_OFFSET); +#endif /* And enable the SPI */ diff --git a/arch/arm/src/samv7/sam_spi.h b/arch/arm/src/samv7/sam_spi.h index 7bbb4d6f358..dded6425348 100644 --- a/arch/arm/src/samv7/sam_spi.h +++ b/arch/arm/src/samv7/sam_spi.h @@ -1,7 +1,7 @@ /**************************************************************************** * arch/arm/src/samv7/sam_spi.h * - * Copyright (C) 2015 Gregory Nutt. All rights reserved. + * Copyright (C) 2015-2016 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -63,26 +63,72 @@ * sam_spibus_initialize(). */ -#define __SPI_CS_SHIFT (0) /* Bits 0-1: SPI chip select number */ -#define __SPI_CS_MASK (3 << __SPI_CS_SHIFT) -# define __SPI_CS0 (0 << __SPI_CS_SHIFT) -# define __SPI_CS1 (1 << __SPI_CS_SHIFT) -# define __SPI_CS2 (2 << __SPI_CS_SHIFT) -# define __SPI_CS3 (3 << __SPI_CS_SHIFT) -#define __SPI_SPI_SHIFT (2) /* Bit 2: SPI controller number */ -#define __SPI_SPI_MASK (1 << __SPI_SPI_SHIFT) -# define __SPI_SPI0 (0 << __SPI_SPI_SHIFT) /* SPI0 */ -# define __SPI_SPI1 (1 << __SPI_SPI_SHIFT) /* SPI1 */ +#ifdef CONFIG_SAMV7_SPI_CS_DECODING -#define SPI0_CS0 (__SPI_SPI0 | __SPI_CS0) -#define SPI0_CS1 (__SPI_SPI0 | __SPI_CS1) -#define SPI0_CS2 (__SPI_SPI0 | __SPI_CS2) -#define SPI0_CS3 (__SPI_SPI0 | __SPI_CS3) +# define __SPI_CS_SHIFT (0) /* Bits 0-3: SPI chip select number */ +# define __SPI_CS_MASK (15 << __SPI_CS_SHIFT) -#define SPI1_CS0 (__SPI_SPI1 | __SPI_CS0) -#define SPI1_CS1 (__SPI_SPI1 | __SPI_CS1) -#define SPI1_CS2 (__SPI_SPI1 | __SPI_CS2) -#define SPI1_CS3 (__SPI_SPI1 | __SPI_CS3) +# define __SPI_SPI_SHIFT (4) /* Bit 4: SPI controller number */ +# define __SPI_SPI_MASK (1 << __SPI_SPI_SHIFT) +# define __SPI_SPI0 (0 << __SPI_SPI_SHIFT) /* SPI0 */ +# define __SPI_SPI1 (1 << __SPI_SPI_SHIFT) /* SPI1 */ + +# define SPI0_CS1 (__SPI_SPI0 | 1) +# define SPI0_CS2 (__SPI_SPI0 | 2) +# define SPI0_CS3 (__SPI_SPI0 | 3) +# define SPI0_CS4 (__SPI_SPI0 | 4) +# define SPI0_CS5 (__SPI_SPI0 | 5) +# define SPI0_CS6 (__SPI_SPI0 | 6) +# define SPI0_CS7 (__SPI_SPI0 | 7) +# define SPI0_CS8 (__SPI_SPI0 | 8) +# define SPI0_CS9 (__SPI_SPI0 | 9) +# define SPI0_CS10 (__SPI_SPI0 | 10) +# define SPI0_CS11 (__SPI_SPI0 | 11) +# define SPI0_CS12 (__SPI_SPI0 | 12) +# define SPI0_CS13 (__SPI_SPI0 | 13) +# define SPI0_CS14 (__SPI_SPI0 | 14) +# define SPI0_CS15 (__SPI_SPI0 | 15) + +# define SPI1_CS1 (__SPI_SPI1 | 1) +# define SPI1_CS2 (__SPI_SPI1 | 2) +# define SPI1_CS3 (__SPI_SPI1 | 3) +# define SPI1_CS4 (__SPI_SPI1 | 4) +# define SPI1_CS5 (__SPI_SPI1 | 5) +# define SPI1_CS6 (__SPI_SPI1 | 6) +# define SPI1_CS7 (__SPI_SPI1 | 7) +# define SPI1_CS8 (__SPI_SPI1 | 8) +# define SPI1_CS9 (__SPI_SPI1 | 9) +# define SPI1_CS10 (__SPI_SPI1 | 10) +# define SPI1_CS11 (__SPI_SPI1 | 11) +# define SPI1_CS12 (__SPI_SPI1 | 12) +# define SPI1_CS13 (__SPI_SPI1 | 13) +# define SPI1_CS14 (__SPI_SPI1 | 14) +# define SPI1_CS15 (__SPI_SPI1 | 15) + +#else /* CONFIG_SAMV7_SPI_CS_DECODING */ + +# define __SPI_CS_SHIFT (0) /* Bits 0-1: SPI chip select number */ +# define __SPI_CS_MASK (3 << __SPI_CS_SHIFT) +# define __SPI_CS0 (0 << __SPI_CS_SHIFT) +# define __SPI_CS1 (1 << __SPI_CS_SHIFT) +# define __SPI_CS2 (2 << __SPI_CS_SHIFT) +# define __SPI_CS3 (3 << __SPI_CS_SHIFT) +# define __SPI_SPI_SHIFT (2) /* Bit 2: SPI controller number */ +# define __SPI_SPI_MASK (1 << __SPI_SPI_SHIFT) +# define __SPI_SPI0 (0 << __SPI_SPI_SHIFT) /* SPI0 */ +# define __SPI_SPI1 (1 << __SPI_SPI_SHIFT) /* SPI1 */ + +# define SPI0_CS0 (__SPI_SPI0 | __SPI_CS0) +# define SPI0_CS1 (__SPI_SPI0 | __SPI_CS1) +# define SPI0_CS2 (__SPI_SPI0 | __SPI_CS2) +# define SPI0_CS3 (__SPI_SPI0 | __SPI_CS3) + +# define SPI1_CS0 (__SPI_SPI1 | __SPI_CS0) +# define SPI1_CS1 (__SPI_SPI1 | __SPI_CS1) +# define SPI1_CS2 (__SPI_SPI1 | __SPI_CS2) +# define SPI1_CS3 (__SPI_SPI1 | __SPI_CS3) + +#endif /* CONFIG_SAMV7_SPI_CS_DECODING */ /**************************************************************************** * Public Types