summaryrefslogtreecommitdiff
path: root/ecos/packages/devs/spi
diff options
context:
space:
mode:
authorMichael Gielda <mgielda@antmicro.com>2014-04-03 14:53:04 +0200
committerMichael Gielda <mgielda@antmicro.com>2014-04-03 14:53:04 +0200
commitae1e4e08a1005a0c487f03ba189d7536e7fdcba6 (patch)
treef1c296f8a966a9a39876b0e98e16d9c5da1776dd /ecos/packages/devs/spi
parentf157da5337118d3c5cd464266796de4262ac9dbd (diff)
Added the OS files
Diffstat (limited to 'ecos/packages/devs/spi')
-rw-r--r--ecos/packages/devs/spi/arm/at91/current/ChangeLog113
-rw-r--r--ecos/packages/devs/spi/arm/at91/current/cdl/spi_at91.cdl225
-rw-r--r--ecos/packages/devs/spi/arm/at91/current/include/spi_at91.h121
-rw-r--r--ecos/packages/devs/spi/arm/at91/current/src/spi_at91.c707
-rw-r--r--ecos/packages/devs/spi/arm/at91/current/src/spi_at91_init.cxx73
-rw-r--r--ecos/packages/devs/spi/arm/eb55/current/ChangeLog50
-rw-r--r--ecos/packages/devs/spi/arm/eb55/current/cdl/spi_eb55.cdl97
-rw-r--r--ecos/packages/devs/spi/arm/eb55/current/include/spi_eb55.h62
-rw-r--r--ecos/packages/devs/spi/arm/eb55/current/src/spi_eb55.c74
-rw-r--r--ecos/packages/devs/spi/arm/lpc2xxx/current/ChangeLog45
-rw-r--r--ecos/packages/devs/spi/arm/lpc2xxx/current/cdl/spi_lpc2xxx.cdl103
-rw-r--r--ecos/packages/devs/spi/arm/lpc2xxx/current/include/spi_lpc2xxx.h108
-rw-r--r--ecos/packages/devs/spi/arm/lpc2xxx/current/src/spi_lpc2xxx.cxx367
-rw-r--r--ecos/packages/devs/spi/cortexm/a2fxxx/current/ChangeLog35
-rw-r--r--ecos/packages/devs/spi/cortexm/a2fxxx/current/cdl/spi_a2fxxx.cdl175
-rw-r--r--ecos/packages/devs/spi/cortexm/a2fxxx/current/include/spi_a2fxxx.h195
-rw-r--r--ecos/packages/devs/spi/cortexm/a2fxxx/current/src/spi_a2fxxx.c638
-rw-r--r--ecos/packages/devs/spi/cortexm/stm32/current/ChangeLog140
-rw-r--r--ecos/packages/devs/spi/cortexm/stm32/current/cdl/spi_stm32.cdl272
-rw-r--r--ecos/packages/devs/spi/cortexm/stm32/current/include/spi_stm32.h182
-rw-r--r--ecos/packages/devs/spi/cortexm/stm32/current/src/spi_stm32.c805
-rw-r--r--ecos/packages/devs/spi/cortexm/stm32/current/tests/loopback.c185
-rw-r--r--ecos/packages/devs/spi/freescale/dspi/current/ChangeLog79
-rw-r--r--ecos/packages/devs/spi/freescale/dspi/current/cdl/spi_freescale_dspi.cdl387
-rw-r--r--ecos/packages/devs/spi/freescale/dspi/current/include/spi_freescale_dspi.h207
-rw-r--r--ecos/packages/devs/spi/freescale/dspi/current/include/spi_freescale_dspi_buses.inl586
-rw-r--r--ecos/packages/devs/spi/freescale/dspi/current/include/spi_freescale_dspi_io.h292
-rw-r--r--ecos/packages/devs/spi/freescale/dspi/current/src/spi_freescale_dspi.c1190
-rw-r--r--ecos/packages/devs/spi/freescale/dspi/current/tests/spi_loopback.c285
29 files changed, 7798 insertions, 0 deletions
diff --git a/ecos/packages/devs/spi/arm/at91/current/ChangeLog b/ecos/packages/devs/spi/arm/at91/current/ChangeLog
new file mode 100644
index 0000000..23cfb31
--- /dev/null
+++ b/ecos/packages/devs/spi/arm/at91/current/ChangeLog
@@ -0,0 +1,113 @@
+2009-04-02 John Dallaway <john@dallaway.org.uk>
+
+ * cdl/spi_at91.cdl: Fix typographical error for
+ CYGINT_DEVS_SPI_ARM_AT91_HAS_BUS1. [ Bugzilla 1000737 ]
+
+2009-02-16 Jonathan Larmour <jifl@eCosCentric.com>
+
+ * src/spi_at91.c (cyg_spi_at91_bus_init): Partially revert change of
+ 2009-02-11. Define an empty CYGBLD_ATTRIB_C_INIT_PRI and rely on
+ spi_at91_init.cxx to call, in case the compiler does not supply
+ that macro (e.g. if too old).
+ * cdl/spi_at91.cdl: Revert change of 2009-02-11.
+ * src/spi_at91_init.cxx: Revive. Set priority to CYG_INIT_BUS_SPI.
+ Conditionalise on CYGBLD_ATTRIB_C_INIT_PRI.
+
+2009-02-12 Nick Garnett <nickg@ecoscentric.com>
+
+ * cdl/spi_at91.cdl: Add a requires for CYGPKG_ERROR.
+
+2009-02-11 Bart Veer <bartv@ecoscentric.com>
+
+ * src/spi_at91.c (cyg_spi_at91_bus_init): turn into a prioritized
+ constructor, make it a static and rename.
+
+ * cdl/spi_at91.cdl: remove src/spi_at91_init.cxx
+
+ * src/spi_at91_init.cxx: removed, no longer needed.
+
+2008-10-19 Igor B. Poretsky <poretsky@mlbox.ru>
+
+ * src/spi_at91.c: Typo fixes from var_io.h. Correctly calculate
+ the board rate. Before it was two times too fast.
+
+2006-09-27 Andrew Lunn <andrew.lunn@ascom.ch>
+
+ * src/spi_at91.c (spi_at91_transaction_begin): Don't use #ifdef
+ inside a macro invocation. The compiler throws a wobbly.
+
+2006-09-07 John Eigelaar <jeigelaar@mweb.co.za>
+
+ * src/spi_at91.c: Fixed the chip select functions.
+ Changed the Mode Register setup as to disable the Mode Failure
+ Detaction for variants that support it. The Mode Failure Detection
+ breaks because NPCS0 is not connected, we are using GPIO, and is
+ thus floating.
+
+2006-06-01 John Eigelaar <jeigelaar@mweb.co.za>
+
+ * src/spi_at91.c:
+ * cdl/spi_at91.cdl:
+ * include/spi_at91.h: Generalize so that multiple SPI
+ busses can be driven.
+
+2006-05-19 Andrew Lunn <andrew.lunn@ascom.ch>
+
+ * src/spi_at91.c: Use the AT91 GPIO/PIO macros to aid
+ portability between different AT91 device.
+
+2004-11-11 Sebastian Block <sebastianblock@gmx.net>
+
+ * src/spi_at91.c: Fixed negation of the chip select signal when
+ not using a 4 to 16 decoder
+
+2004-10-13 Savin Zlobec <savin@elatec.si>
+
+ * src/spi_at91.c: Fixed a typo in spi_at91_transfer reported by
+ Nicolas Brouard.
+
+2004-08-31 Savin Zlobec <savin@elatec.si>
+
+ * include/spi_at91.h:
+ * src/spi_at91.c:
+ Moved SPI registers and bits defines to HAL headers, added support
+ for 4 to 16 decoder of chip select signals, support for transfers
+ larger than 2^16 and per device configurable delay between two
+ transfers.
+ * cdl/spi_at91.cdl:
+ Added option to enable support for 4 to 16 decoder of chip select
+ signals.
+
+2004-08-27 Savin Zlobec <savin@elatec.si>
+
+ * cdl/spi_at91.cdl:
+ * include/spi_at91.h:
+ * src/spi_at91.c:
+ * src/spi_at91_init.cxx:
+ Atmel AT91 SPI bus driver implementation.
+
+
+
+//===========================================================================
+// ####GPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2009 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 or (at your option) any
+// later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc., 51 Franklin Street,
+// Fifth Floor, Boston, MA 02110-1301, USA.
+// -------------------------------------------
+// ####GPLCOPYRIGHTEND####
+//===========================================================================
diff --git a/ecos/packages/devs/spi/arm/at91/current/cdl/spi_at91.cdl b/ecos/packages/devs/spi/arm/at91/current/cdl/spi_at91.cdl
new file mode 100644
index 0000000..e366daf
--- /dev/null
+++ b/ecos/packages/devs/spi/arm/at91/current/cdl/spi_at91.cdl
@@ -0,0 +1,225 @@
+# ====================================================================
+#
+# spi_at91.cdl
+#
+# Atmel AT91 (ARM) SPI driver configuration data
+#
+# ====================================================================
+## ####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating System.
+## Copyright (C) 1998, 1999, 2000, 2001, 2002, 2009 Free Software Foundation, Inc.
+##
+## eCos is free software; you can redistribute it and/or modify it under
+## the terms of the GNU General Public License as published by the Free
+## Software Foundation; either version 2 or (at your option) any later
+## version.
+##
+## eCos is distributed in the hope that it will be useful, but WITHOUT
+## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+## for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with eCos; if not, write to the Free Software Foundation, Inc.,
+## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+##
+## As a special exception, if other files instantiate templates or use
+## macros or inline functions from this file, or you compile this file
+## and link it with other works to produce a work based on this file,
+## this file does not by itself cause the resulting work to be covered by
+## the GNU General Public License. However the source code for this file
+## must still be made available in accordance with section (3) of the GNU
+## General Public License v2.
+##
+## This exception does not invalidate any other reasons why a work based
+## on this file might be covered by the GNU General Public License.
+## -------------------------------------------
+## ####ECOSGPLCOPYRIGHTEND####
+# ====================================================================
+######DESCRIPTIONBEGIN####
+#
+# Author(s): Savin Zlobec <savin@elatec.si>
+# Date: 2004-08-25
+#
+#####DESCRIPTIONEND####
+#
+# ====================================================================
+
+cdl_package CYGPKG_DEVS_SPI_ARM_AT91 {
+ parent CYGPKG_IO_SPI
+ active_if CYGPKG_IO_SPI
+ display "Atmel AT91 SPI driver"
+ requires CYGPKG_HAL_ARM_AT91
+ requires CYGPKG_ERROR
+ hardware
+ include_dir cyg/io
+ compile spi_at91.c
+ compile -library=libextras.a spi_at91_init.cxx
+
+ cdl_option CYGHWR_DEVS_SPI_ARM_AT91_BUS0 {
+ display "Enable support for SPI bus 0"
+ flavor bool
+ default_value 1
+ description "Enable this option to add support for the first
+ SPI peripheral. The most AT91 devices only have one bus"
+ }
+
+ cdl_interface CYGINT_DEVS_SPI_ARM_AT91_HAS_BUS1 {
+ description "
+ This interface is implemented by HALs for devices which have
+ the second SPI bus controller."
+ }
+
+
+ cdl_option CYGHWR_DEVS_SPI_ARM_AT91_BUS1 {
+ active_if CYGINT_DEVS_SPI_ARM_AT91_HAS_BUS1
+ display "Enable support for SPI bus 1"
+ flavor bool
+ default_value 0
+ description "Enable this option to add support for the second
+ SPI peripheral. The most AT91 devices only have one bus"
+ }
+
+ cdl_component CYGPKG_DEVS_SPI_ARM_AT91_BUS0_CFG {
+ active_if CYGHWR_DEVS_SPI_ARM_AT91_BUS0
+ display "Configuration options for SPI Bus 0"
+ flavor none
+ description "This is the configuration options for SPI Bus 0"
+
+ cdl_option CYGHWR_DEVS_SPI_ARM_AT91_BUS0_PCSDEC {
+ display "Support 4 to 16 decoder of chip select signals."
+ flavor bool
+ default_value 0
+ description "Enable this option if SPI peripheral chip
+ selects are connected through an 4 to 16 decoder."
+ }
+
+ cdl_option CYGDAT_DEVS_SPI_ARM_AT91_BUS0_NPCS0 {
+ display "PIO-Pin used for NPSC0"
+ flavor data
+ default_value {"AT91_SPI_NPCS0"}
+ description "Any GPIO pin is able to be used as the SPI driver
+ uses GPIO to control the chip selects. Specify the pin
+ as \"AT91_GPIO_PA13\" or \"AT91_GPIO_PB5\" etc. Specify
+ \"NONE\" if this chip select is to be disabled"
+ }
+
+ cdl_option CYGDAT_DEVS_SPI_ARM_AT91_BUS0_NPCS1 {
+ display "PIO-Pin used for NPSC1"
+ flavor data
+ default_value {"AT91_SPI_NPCS1"}
+ description "Any GPIO pin is able to be used as the SPI driver
+ uses GPIO to control the chip selects. Specify the pin
+ as \"AT91_GPIO_PA13\" or \"AT91_GPIO_PB5\" etc. Specify
+ \"NONE\" if this chip select is to be disabled"
+ }
+ cdl_option CYGDAT_DEVS_SPI_ARM_AT91_BUS0_NPCS2 {
+ display "PIO-Pin used for NPSC2"
+ flavor data
+ default_value {"AT91_SPI_NPCS2"}
+ description "Any GPIO pin is able to be used as the SPI driver
+ uses GPIO to control the chip selects. Specify the pin
+ as \"AT91_GPIO_PA13\" or \"AT91_GPIO_PB5\" etc. Specify
+ \"NONE\" if this chip select is to be disabled"
+ }
+ cdl_option CYGDAT_DEVS_SPI_ARM_AT91_BUS0_NPCS3 {
+ display "PIO-Pin used for NPSC3"
+ flavor data
+ default_value {"AT91_SPI_NPCS3"}
+ description "Any GPIO pin is able to be used as the SPI driver
+ uses GPIO to control the chip selects. Specify the pin
+ as \"AT91_GPIO_PA13\" or \"AT91_GPIO_PB5\" etc. Specify
+ \"NONE\" if this chip select is to be disabled"
+ }
+
+ }
+
+ cdl_component CYGPKG_DEVS_SPI_ARM_AT91_BUS1_CFG {
+ active_if CYGHWR_DEVS_SPI_ARM_AT91_BUS1
+ display "Configuration options for SPI Bus 1"
+ flavor none
+ description "This is the configuration options for SPI Bus 1"
+
+ cdl_option CYGHWR_DEVS_SPI_ARM_AT91_BUS1_PCSDEC {
+ display "Support 4 to 16 decoder of chip select signals."
+ flavor bool
+ default_value 0
+ description "Enable this option if SPI peripheral chip
+ selects are connected through an 4 to 16 decoder."
+ }
+
+ cdl_option CYGDAT_DEVS_SPI_ARM_AT91_BUS1_NPCS0 {
+ display "PIO-Pin used for NPSC0"
+ flavor data
+ default_value {"AT91_SPI1_NPCS0"}
+ description "Any GPIO pin is able to be used as the SPI driver
+ uses GPIO to control the chip selects. Specify the pin
+ as \"AT91_GPIO_PA13\" or \"AT91_GPIO_PB5\" etc. Specify
+ \"NONE\" if this chip select is to be disabled"
+ }
+
+ cdl_option CYGDAT_DEVS_SPI_ARM_AT91_BUS1_NPCS1 {
+ display "PIO-Pin used for NPSC1"
+ flavor data
+ default_value {"AT91_SPI1_NPCS1"}
+ description "Any GPIO pin is able to be used as the SPI driver
+ uses GPIO to control the chip selects. Specify the pin
+ as \"AT91_GPIO_PA13\" or \"AT91_GPIO_PB5\" etc. Specify
+ \"NONE\" if this chip select is to be disabled"
+ }
+ cdl_option CYGDAT_DEVS_SPI_ARM_AT91_BUS1_NPCS2 {
+ display "PIO-Pin used for NPSC2"
+ flavor data
+ default_value {"AT91_SPI1_NPCS2"}
+ description "Any GPIO pin is able to be used as the SPI driver
+ uses GPIO to control the chip selects. Specify the pin
+ as \"AT91_GPIO_PA13\" or \"AT91_GPIO_PB5\" etc. Specify
+ \"NONE\" if this chip select is to be disabled"
+ }
+ cdl_option CYGDAT_DEVS_SPI_ARM_AT91_BUS1_NPCS3 {
+ display "PIO-Pin used for NPSC3"
+ flavor data
+ default_value {"AT91_SPI1_NPCS3"}
+ description "Any GPIO pin is able to be used as the SPI driver
+ uses GPIO to control the chip selects. Specify the pin
+ as \"AT91_GPIO_PA13\" or \"AT91_GPIO_PB5\" etc. Specify
+ \"NONE\" if this chip select is to be disabled"
+ }
+
+ }
+
+
+ cdl_component CYGPKG_DEVS_SPI_ARM_AT91_OPTIONS {
+ display "Atmel AT91 SPI driver build options"
+ flavor none
+ description "
+ Package specific build options including control over
+ compiler flags used only in building this package,
+ and details of which tests are built."
+
+ cdl_option CYGPKG_DEVS_SPI_ARM_AT91_CFLAGS_ADD {
+ display "Additional compiler flags"
+ flavor data
+ no_define
+ default_value { "" }
+ description "
+ This option modifies the set of compiler flags for
+ building the SPI device. These flags are used in addition
+ to the set of global flags."
+ }
+
+ cdl_option CYGPKG_DEVS_SPI_ARM_AT91_CFLAGS_REMOVE {
+ display "Suppressed compiler flags"
+ flavor data
+ no_define
+ default_value { "" }
+ description "
+ This option modifies the set of compiler flags for
+ building the SPI device. These flags are removed from
+ the set of global flags if present."
+ }
+ }
+}
+
+# EOF spi_at91.cdl
diff --git a/ecos/packages/devs/spi/arm/at91/current/include/spi_at91.h b/ecos/packages/devs/spi/arm/at91/current/include/spi_at91.h
new file mode 100644
index 0000000..e64f63c
--- /dev/null
+++ b/ecos/packages/devs/spi/arm/at91/current/include/spi_at91.h
@@ -0,0 +1,121 @@
+#ifndef CYGONCE_DEVS_SPI_ARM_AT91_H
+#define CYGONCE_DEVS_SPI_ARM_AT91_H
+//==========================================================================
+//
+// spi_at91.h
+//
+// Atmel AT91 (ARM) SPI driver defines
+//
+//==========================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later
+// version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with eCos; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// As a special exception, if other files instantiate templates or use
+// macros or inline functions from this file, or you compile this file
+// and link it with other works to produce a work based on this file,
+// this file does not by itself cause the resulting work to be covered by
+// the GNU General Public License. However the source code for this file
+// must still be made available in accordance with section (3) of the GNU
+// General Public License v2.
+//
+// This exception does not invalidate any other reasons why a work based
+// on this file might be covered by the GNU General Public License.
+// -------------------------------------------
+// ####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Savin Zlobec <savin@elatec.si>
+// Date: 2004-08-25
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#include <pkgconf/hal.h>
+#include <pkgconf/io_spi.h>
+
+#include <cyg/infra/cyg_type.h>
+#include <cyg/hal/drv_api.h>
+#include <cyg/io/spi.h>
+
+//-----------------------------------------------------------------------------
+// AT91 SPI BUS
+
+typedef struct cyg_spi_at91_bus_s
+{
+ // ---- Upper layer data ----
+
+ cyg_spi_bus spi_bus; // Upper layer SPI bus data
+
+ // ---- Lower layer data ----
+
+ cyg_interrupt spi_interrupt; // SPI interrupt object
+ cyg_handle_t spi_interrupt_handle; // SPI interrupt handle
+ cyg_drv_mutex_t transfer_mx; // Transfer mutex
+ cyg_drv_cond_t transfer_cond; // Transfer condition
+ cyg_bool transfer_end; // Transfer end flag
+ cyg_bool cs_up; // Chip Select up flag
+ cyg_vector_t interrupt_number; // SPI Interrupt Number
+ cyg_addrword_t base; // Base Address of the SPI peripheral
+ cyg_uint8 cs_en[4]; // The Configurations state for the CS
+ cyg_uint32 cs_gpio[4]; // The GPIO Configurations for the CS
+} cyg_spi_at91_bus_t;
+
+//-----------------------------------------------------------------------------
+// AT91 SPI DEVICE
+
+typedef struct cyg_spi_at91_device_s
+{
+ // ---- Upper layer data ----
+
+ cyg_spi_device spi_device; // Upper layer SPI device data
+
+ // ---- Lower layer data (configurable) ----
+
+ cyg_uint8 dev_num; // Device number
+ cyg_uint8 cl_pol; // Clock polarity (0 or 1)
+ cyg_uint8 cl_pha; // Clock phase (0 or 1)
+ cyg_uint32 cl_brate; // Clock baud rate
+ cyg_uint16 cs_up_udly; // Delay in us between CS up and transfer start
+ cyg_uint16 cs_dw_udly; // Delay in us between transfer end and CS down
+ cyg_uint16 tr_bt_udly; // Delay in us between two transfers
+
+ // ---- Lower layer data (internal) ----
+
+ cyg_bool init; // Is device initialized
+ cyg_uint8 cl_scbr; // Value of SCBR (SPI clock) reg field
+ cyg_uint8 cl_div32; // Divide SPI master clock by 32
+} cyg_spi_at91_device_t;
+
+//-----------------------------------------------------------------------------
+// AT91 SPI exported busses
+
+/* For backwards compatability */
+#define cyg_spi_at91_bus cyg_spi_at91_bus0
+
+externC cyg_spi_at91_bus_t cyg_spi_at91_bus0;
+externC cyg_spi_at91_bus_t cyg_spi_at91_bus1;
+
+//-----------------------------------------------------------------------------
+
+#endif // CYGONCE_DEVS_SPI_ARM_AT91_H
+
+//-----------------------------------------------------------------------------
+// End of spi_at91.h
diff --git a/ecos/packages/devs/spi/arm/at91/current/src/spi_at91.c b/ecos/packages/devs/spi/arm/at91/current/src/spi_at91.c
new file mode 100644
index 0000000..a64bec8
--- /dev/null
+++ b/ecos/packages/devs/spi/arm/at91/current/src/spi_at91.c
@@ -0,0 +1,707 @@
+//==========================================================================
+//
+// spi_at91.c
+//
+// Atmel AT91 (ARM) SPI driver
+//
+//==========================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2009 Free Software Foundation, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later
+// version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with eCos; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// As a special exception, if other files instantiate templates or use
+// macros or inline functions from this file, or you compile this file
+// and link it with other works to produce a work based on this file,
+// this file does not by itself cause the resulting work to be covered by
+// the GNU General Public License. However the source code for this file
+// must still be made available in accordance with section (3) of the GNU
+// General Public License v2.
+//
+// This exception does not invalidate any other reasons why a work based
+// on this file might be covered by the GNU General Public License.
+// -------------------------------------------
+// ####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Savin Zlobec <savin@elatec.si>
+// Date: 2004-08-25
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#include <pkgconf/hal.h>
+#include <pkgconf/io_spi.h>
+#include <pkgconf/devs_spi_arm_at91.h>
+
+#include <cyg/infra/cyg_type.h>
+#include <cyg/infra/cyg_ass.h>
+#include <cyg/hal/hal_io.h>
+#include <cyg/hal/hal_if.h>
+#include <cyg/hal/hal_intr.h>
+#include <cyg/hal/drv_api.h>
+#include <cyg/io/spi.h>
+#include <cyg/io/spi_at91.h>
+#include <cyg/error/codes.h>
+
+// -------------------------------------------------------------------------
+static void spi_at91_init_bus(cyg_spi_at91_bus_t * bus);
+
+static cyg_uint32 spi_at91_ISR(cyg_vector_t vector, cyg_addrword_t data);
+
+static void spi_at91_DSR(cyg_vector_t vector,
+ cyg_ucount32 count,
+ cyg_addrword_t data);
+
+static void spi_at91_transaction_begin(cyg_spi_device *dev);
+
+static void spi_at91_transaction_transfer(cyg_spi_device *dev,
+ cyg_bool polled,
+ cyg_uint32 count,
+ const cyg_uint8 *tx_data,
+ cyg_uint8 *rx_data,
+ cyg_bool drop_cs);
+
+static void spi_at91_transaction_tick(cyg_spi_device *dev,
+ cyg_bool polled,
+ cyg_uint32 count);
+
+static void spi_at91_transaction_end(cyg_spi_device* dev);
+
+static int spi_at91_get_config(cyg_spi_device *dev,
+ cyg_uint32 key,
+ void *buf,
+ cyg_uint32 *len);
+
+static int spi_at91_set_config(cyg_spi_device *dev,
+ cyg_uint32 key,
+ const void *buf,
+ cyg_uint32 *len);
+
+// -------------------------------------------------------------------------
+// AT91 SPI BUS
+
+#ifdef CYGHWR_DEVS_SPI_ARM_AT91_BUS0
+cyg_spi_at91_bus_t cyg_spi_at91_bus0 = {
+ .spi_bus.spi_transaction_begin = spi_at91_transaction_begin,
+ .spi_bus.spi_transaction_transfer = spi_at91_transaction_transfer,
+ .spi_bus.spi_transaction_tick = spi_at91_transaction_tick,
+ .spi_bus.spi_transaction_end = spi_at91_transaction_end,
+ .spi_bus.spi_get_config = spi_at91_get_config,
+ .spi_bus.spi_set_config = spi_at91_set_config,
+ .interrupt_number = CYGNUM_HAL_INTERRUPT_SPI,
+ .base = AT91_SPI,
+#ifndef CYGDAT_DEVS_SPI_ARM_AT91_BUS0_NPCS0_NONE
+ .cs_en[0] = true,
+ .cs_gpio[0] = CYGDAT_DEVS_SPI_ARM_AT91_BUS0_NPCS0,
+#else
+ .cs_en[0] = false,
+#endif
+#ifndef CYGDAT_DEVS_SPI_ARM_AT91_BUS0_NPCS1_NONE
+ .cs_en[1] = true,
+ .cs_gpio[1] = CYGDAT_DEVS_SPI_ARM_AT91_BUS0_NPCS1,
+#else
+ .cs_en[1] = false,
+#endif
+#ifndef CYGDAT_DEVS_SPI_ARM_AT91_BUS0_NPCS2_NONE
+ .cs_en[2] = true,
+ .cs_gpio[2] = CYGDAT_DEVS_SPI_ARM_AT91_BUS0_NPCS2,
+#else
+ .cs_en[2] = false,
+#endif
+#ifndef CYGDAT_DEVS_SPI_ARM_AT91_BUS0_NPCS3_NONE
+ .cs_en[3] = true,
+ .cs_gpio[3] = CYGDAT_DEVS_SPI_ARM_AT91_BUS0_NPCS3,
+#else
+ .cs_en[3] = false,
+#endif
+};
+
+CYG_SPI_DEFINE_BUS_TABLE(cyg_spi_at91_device_t, 0);
+#endif
+#ifdef CYGHWR_DEVS_SPI_ARM_AT91_BUS1
+cyg_spi_at91_bus_t cyg_spi_at91_bus1 = {
+ .spi_bus.spi_transaction_begin = spi_at91_transaction_begin,
+ .spi_bus.spi_transaction_transfer = spi_at91_transaction_transfer,
+ .spi_bus.spi_transaction_tick = spi_at91_transaction_tick,
+ .spi_bus.spi_transaction_end = spi_at91_transaction_end,
+ .spi_bus.spi_get_config = spi_at91_get_config,
+ .spi_bus.spi_set_config = spi_at91_set_config,
+ .interrupt_number = CYGNUM_HAL_INTERRUPT_SPI1,
+ .base = AT91_SPI1,
+#ifndef CYGDAT_DEVS_SPI_ARM_AT91_BUS1_NPCS0_NONE
+ .cs_en[0] = true,
+ .cs_gpio[0] = CYGDAT_DEVS_SPI_ARM_AT91_BUS1_NPCS0,
+#else
+ .cs_en[0] = false,
+#endif
+#ifndef CYGDAT_DEVS_SPI_ARM_AT91_BUS1_NPCS1_NONE
+ .cs_en[1] = true,
+ .cs_gpio[1] = CYGDAT_DEVS_SPI_ARM_AT91_BUS1_NPCS1,
+#else
+ .cs_en[1] = false,
+#endif
+#ifndef CYGDAT_DEVS_SPI_ARM_AT91_BUS1_NPCS2_NONE
+ .cs_en[2] = true,
+ .cs_gpio[2] = CYGDAT_DEVS_SPI_ARM_AT91_BUS1_NPCS2,
+#else
+ .cs_en[2] = false,
+#endif
+#ifndef CYGDAT_DEVS_SPI_ARM_AT91_BUS1_NPCS3_NONE
+ .cs_en[3] = true,
+ .cs_gpio[3] = CYGDAT_DEVS_SPI_ARM_AT91_BUS1_NPCS3,
+#else
+ .cs_en[3] = false,
+#endif
+};
+
+CYG_SPI_DEFINE_BUS_TABLE(cyg_spi_at91_device_t, 1);
+#endif
+// -------------------------------------------------------------------------
+
+// If C constructor with init priority functionality is not in compiler,
+// rely on spi_at91_init.cxx to init us.
+#ifndef CYGBLD_ATTRIB_C_INIT_PRI
+# define CYGBLD_ATTRIB_C_INIT_PRI(x)
+#endif
+
+void CYGBLD_ATTRIB_C_INIT_PRI(CYG_INIT_BUS_SPI)
+cyg_spi_at91_bus_init(void)
+{
+
+#ifdef CYGHWR_DEVS_SPI_ARM_AT91_BUS0
+ // NOTE: here we let the SPI controller control
+ // the data in, out and clock signals, but
+ // we need to handle the chip selects manually
+ // in order to achieve better chip select control
+ // in between transactions.
+
+ // Put SPI MISO, MOSI and SPCK pins into peripheral mode
+ HAL_ARM_AT91_PIO_CFG(AT91_SPI_SPCK);
+ HAL_ARM_AT91_PIO_CFG(AT91_SPI_MISO);
+ HAL_ARM_AT91_PIO_CFG(AT91_SPI_MOSI);
+ spi_at91_init_bus(&cyg_spi_at91_bus0);
+#endif
+#ifdef CYGHWR_DEVS_SPI_ARM_AT91_BUS1
+ // NOTE: here we let the SPI controller control
+ // the data in, out and clock signals, but
+ // we need to handle the chip selects manually
+ // in order to achieve better chip select control
+ // in between transactions.
+
+ // Put SPI MISO, MOSI and SPCK pins into peripheral mode
+ HAL_ARM_AT91_PIO_CFG(AT91_SPI1_SPCK);
+ HAL_ARM_AT91_PIO_CFG(AT91_SPI1_MISO);
+ HAL_ARM_AT91_PIO_CFG(AT91_SPI1_MOSI);
+ spi_at91_init_bus(&cyg_spi_at91_bus1);
+#endif
+}
+
+// -------------------------------------------------------------------------
+
+static void spi_at91_init_bus(cyg_spi_at91_bus_t * spi_bus)
+{
+ cyg_uint32 ctr;
+ // Create and attach SPI interrupt object
+ cyg_drv_interrupt_create(spi_bus->interrupt_number,
+ 4,
+ (cyg_addrword_t)spi_bus,
+ spi_at91_ISR,
+ spi_at91_DSR,
+ &spi_bus->spi_interrupt_handle,
+ &spi_bus->spi_interrupt);
+
+ cyg_drv_interrupt_attach(spi_bus->spi_interrupt_handle);
+
+ // Init transfer mutex and condition
+ cyg_drv_mutex_init(&spi_bus->transfer_mx);
+ cyg_drv_cond_init(&spi_bus->transfer_cond,
+ &spi_bus->transfer_mx);
+
+ // Init flags
+ spi_bus->transfer_end = true;
+ spi_bus->cs_up = false;
+
+ // Soft reset the SPI controller
+ HAL_WRITE_UINT32(spi_bus->base+AT91_SPI_CR, AT91_SPI_CR_SWRST);
+
+ // Configure SPI pins
+
+
+ // Put SPI chip select pins in IO output mode
+ for(ctr = 0;ctr<4;ctr++)
+ {
+ if(spi_bus->cs_en[ctr])
+ {
+ HAL_ARM_AT91_GPIO_CFG_DIRECTION(spi_bus->cs_gpio[ctr],AT91_PIN_OUT);
+ HAL_ARM_AT91_GPIO_SET(spi_bus->cs_gpio[ctr]);
+ }
+ }
+ // Call upper layer bus init
+ CYG_SPI_BUS_COMMON_INIT(&spi_bus->spi_bus);
+}
+
+static cyg_uint32
+spi_at91_ISR(cyg_vector_t vector, cyg_addrword_t data)
+{
+ cyg_uint32 stat;
+ cyg_spi_at91_bus_t * spi_bus = (cyg_spi_at91_bus_t *)data;
+ // Read the status register and disable
+ // the SPI int events that have occurred
+
+ HAL_READ_UINT32(spi_bus->base+AT91_SPI_SR, stat);
+ HAL_WRITE_UINT32(spi_bus->base+AT91_SPI_IDR, stat);
+
+ cyg_drv_interrupt_mask(vector);
+ cyg_drv_interrupt_acknowledge(vector);
+
+ return CYG_ISR_CALL_DSR;
+}
+
+static void
+spi_at91_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
+{
+ cyg_spi_at91_bus_t *spi_bus = (cyg_spi_at91_bus_t *) data;
+ cyg_uint32 stat;
+
+ // Read the status register and
+ // check for transfer completion
+
+ HAL_READ_UINT32(spi_bus->base+AT91_SPI_SR, stat);
+
+ if((stat & AT91_SPI_SR_ENDRX) && (stat & AT91_SPI_SR_ENDTX))
+ {
+ // Transfer ended
+ spi_bus->transfer_end = true;
+ cyg_drv_cond_signal(&spi_bus->transfer_cond);
+ }
+ else
+ {
+ // Transfer still in progress - unmask the SPI
+ // int so we can get more SPI int events
+ cyg_drv_interrupt_unmask(vector);
+ }
+}
+
+static cyg_bool
+spi_at91_calc_scbr(cyg_spi_at91_device_t *dev)
+{
+ cyg_uint32 scbr;
+ cyg_bool res = true;
+
+ // Calculate SCBR from baud rate
+
+ scbr = CYGNUM_HAL_ARM_AT91_CLOCK_SPEED / dev->cl_brate;
+ if ((2*(CYGNUM_HAL_ARM_AT91_CLOCK_SPEED % dev->cl_brate)) >= dev->cl_brate)
+ scbr++;
+
+ if (scbr < 2)
+ {
+ dev->cl_scbr = 2;
+ dev->cl_div32 = 0;
+ res = false;
+ }
+ else if (scbr > 255)
+ {
+ dev->cl_div32 = 1;
+
+ scbr = CYGNUM_HAL_ARM_AT91_CLOCK_SPEED / (32*dev->cl_brate);
+
+ if (scbr < 2)
+ {
+ dev->cl_scbr = 2;
+ res = false;
+ }
+ else if (scbr > 255)
+ {
+ dev->cl_scbr = 255;
+ res = false;
+ }
+ else
+ dev->cl_scbr = (cyg_uint8)scbr;
+ }
+ else
+ {
+ dev->cl_scbr = (cyg_uint8)scbr;
+ dev->cl_div32 = 0;
+ }
+
+ return res;
+}
+
+static void
+spi_at91_set_npcs(cyg_spi_at91_bus_t *spi_bus,int val)
+{
+ cyg_uint32 ctr;
+ for(ctr=0;ctr<4;ctr++)
+ {
+ if(spi_bus->cs_en[ctr])
+ {
+ HAL_ARM_AT91_GPIO_PUT(spi_bus->cs_gpio[ctr], (val & (1<<ctr)));
+ }
+ }
+}
+
+static void
+spi_at91_start_transfer(cyg_spi_at91_device_t *dev)
+{
+ cyg_spi_at91_bus_t *spi_bus = (cyg_spi_at91_bus_t *)dev->spi_device.spi_bus;
+
+ if (spi_bus->cs_up)
+ return;
+
+ // Force minimal delay between two transfers - in case two transfers
+ // follow each other w/o delay, then we have to wait here in order for
+ // the peripheral device to detect cs transition from inactive to active.
+ CYGACC_CALL_IF_DELAY_US(dev->tr_bt_udly);
+
+ // Raise CS
+
+#ifdef CYGHWR_DEVS_SPI_ARM_AT91_PCSDEC
+ spi_at91_set_npcs(spi_bus,~dev->dev_num);
+#else
+ spi_at91_set_npcs(spi_bus,~(1<<dev->dev_num));
+#endif
+ CYGACC_CALL_IF_DELAY_US(dev->cs_up_udly);
+
+ spi_bus->cs_up = true;
+}
+
+static void
+spi_at91_drop_cs(cyg_spi_at91_device_t *dev)
+{
+ cyg_spi_at91_bus_t *spi_bus = (cyg_spi_at91_bus_t *)dev->spi_device.spi_bus;
+
+ if (!spi_bus->cs_up)
+ return;
+
+ // Drop CS
+
+ CYGACC_CALL_IF_DELAY_US(dev->cs_dw_udly);
+ spi_at91_set_npcs(spi_bus,0x0F);
+ spi_bus->cs_up = false;
+}
+
+static void
+spi_at91_transfer(cyg_spi_at91_device_t *dev,
+ cyg_uint32 count,
+ const cyg_uint8 *tx_data,
+ cyg_uint8 *rx_data)
+{
+ cyg_spi_at91_bus_t *spi_bus = (cyg_spi_at91_bus_t *)dev->spi_device.spi_bus;
+
+ // Since PDC transfer buffer counters are 16 bit long,
+ // we have to split longer transfers into chunks.
+ while (count > 0)
+ {
+ cyg_uint16 tr_count = count > 0xFFFF ? 0xFFFF : count;
+
+ // Set rx buf pointer and counter
+ if (NULL != rx_data)
+ {
+ HAL_WRITE_UINT32(spi_bus->base+AT91_SPI_RPR, (cyg_uint32)rx_data);
+ HAL_WRITE_UINT32(spi_bus->base+AT91_SPI_RCR, (cyg_uint32)tr_count);
+ }
+
+ // Set tx buf pointer and counter
+ HAL_WRITE_UINT32(spi_bus->base+AT91_SPI_TPR, (cyg_uint32)tx_data);
+ HAL_WRITE_UINT32(spi_bus->base+AT91_SPI_TCR, (cyg_uint32)tr_count);
+
+#ifdef AT91_SPI_PTCR
+ HAL_WRITE_UINT32(spi_bus->base+AT91_SPI_PTCR,
+ AT91_SPI_PTCR_RXTEN | AT91_SPI_PTCR_TXTEN);
+#endif
+ // Enable the SPI int events we are interested in
+ HAL_WRITE_UINT32(spi_bus->base+AT91_SPI_IER,
+ AT91_SPI_SR_ENDRX | AT91_SPI_SR_ENDTX);
+
+ cyg_drv_mutex_lock(&spi_bus->transfer_mx);
+ {
+ spi_bus->transfer_end = false;
+
+ // Unmask the SPI int
+ cyg_drv_interrupt_unmask(spi_bus->interrupt_number);
+
+ // Wait for its completion
+ cyg_drv_dsr_lock();
+ {
+ while (!spi_bus->transfer_end)
+ cyg_drv_cond_wait(&spi_bus->transfer_cond);
+ }
+ cyg_drv_dsr_unlock();
+ }
+ cyg_drv_mutex_unlock(&spi_bus->transfer_mx);
+
+ if (NULL == rx_data)
+ {
+ cyg_uint32 val;
+
+ // If rx buffer was NULL, then the PDC receiver data transfer
+ // was not started and we didn't wait for ENDRX, but only for
+ // ENDTX. Meaning that right now the last byte is being serialized
+ // over the line and when finished input data will appear in
+ // rx data reg. We have to wait for this to happen here, if we
+ // don't we'll get the last received byte as the first one in the
+ // next transfer!
+
+ // FIXME: is there any better way to do this?
+ // If not, then precalculate this value.
+ val = 8000000/dev->cl_brate;
+ CYGACC_CALL_IF_DELAY_US(val > 1 ? val : 1);
+
+ // Clear the rx data reg
+ HAL_READ_UINT32(spi_bus->base+AT91_SPI_RDR, val);
+ }
+
+ // Adjust running variables
+
+ if (NULL != rx_data)
+ rx_data += tr_count;
+ tx_data += tr_count;
+ count -= tr_count;
+ }
+}
+
+static void
+spi_at91_transfer_polled(cyg_spi_at91_device_t *dev,
+ cyg_uint32 count,
+ const cyg_uint8 *tx_data,
+ cyg_uint8 *rx_data)
+{
+ cyg_uint32 val;
+ cyg_spi_at91_bus_t *spi_bus = (cyg_spi_at91_bus_t *)dev->spi_device.spi_bus;
+
+ // Transmit and receive byte by byte
+ while (count-- > 0)
+ {
+ // Wait for transmit data register empty
+ do
+ {
+ HAL_READ_UINT32(spi_bus->base+AT91_SPI_SR, val);
+ } while ( !(val & AT91_SPI_SR_TDRE) );
+
+ // Send next byte over the wire
+ val = *tx_data++;
+ HAL_WRITE_UINT32(spi_bus->base+AT91_SPI_TDR, val);
+
+ // Wait for reveive data register full
+ do
+ {
+ HAL_READ_UINT32(spi_bus->base+AT91_SPI_SR, val);
+ } while ( !(val & AT91_SPI_SR_RDRF) );
+
+ // Store received byte
+ HAL_READ_UINT32(spi_bus->base+AT91_SPI_RDR, val);
+ if (NULL != rx_data)
+ *rx_data++ = val;
+ }
+}
+
+// -------------------------------------------------------------------------
+
+static void
+spi_at91_transaction_begin(cyg_spi_device *dev)
+{
+ cyg_spi_at91_device_t *at91_spi_dev = (cyg_spi_at91_device_t *) dev;
+ cyg_spi_at91_bus_t *spi_bus =
+ (cyg_spi_at91_bus_t *)at91_spi_dev->spi_device.spi_bus;
+ cyg_uint32 val;
+
+ if (!at91_spi_dev->init)
+ {
+ at91_spi_dev->init = true;
+ spi_at91_calc_scbr(at91_spi_dev);
+ }
+
+ // Configure SPI channel 0 - this is the only channel we
+ // use for all devices since we drive chip selects manually
+
+ val = AT91_SPI_CSR_BITS8;
+
+ if (1 == at91_spi_dev->cl_pol)
+ val |= AT91_SPI_CSR_CPOL;
+
+ if (1 == at91_spi_dev->cl_pha)
+ val |= AT91_SPI_CSR_NCPHA;
+
+ val |= AT91_SPI_CSR_SCBR(at91_spi_dev->cl_scbr);
+
+ HAL_WRITE_UINT32(spi_bus->base+AT91_SPI_CSR0, val);
+
+ // Enable SPI clock
+ HAL_WRITE_UINT32(AT91_PMC+AT91_PMC_PCER, 1<<spi_bus->interrupt_number);
+
+ // Enable the SPI controller
+ HAL_WRITE_UINT32(spi_bus->base+AT91_SPI_CR, AT91_SPI_CR_SPIEN);
+
+ /* As we are using this driver only in master mode with NPCS0
+ configured as GPIO instead of a peripheral pin, it is necessary
+ for the Mode Failure detection to be switched off as this will
+ cause havoc with the driver */
+
+ // Put SPI bus into master mode
+ if (1 == at91_spi_dev->cl_div32) {
+ val = AT91_SPI_MR_MSTR | AT91_SPI_MR_DIV32;
+#ifdef AT91_SPI_MR_MODFDIS
+ val |= AT91_SPI_MR_MODFDIS;
+#endif
+ HAL_WRITE_UINT32(spi_bus->base+AT91_SPI_MR, val);
+ } else {
+ val = AT91_SPI_MR_MSTR;
+#ifdef AT91_SPI_MR_MODFDIS
+ val |= AT91_SPI_MR_MODFDIS;
+#endif
+ HAL_WRITE_UINT32(spi_bus->base+AT91_SPI_MR, val);
+ }
+}
+
+static void
+spi_at91_transaction_transfer(cyg_spi_device *dev,
+ cyg_bool polled,
+ cyg_uint32 count,
+ const cyg_uint8 *tx_data,
+ cyg_uint8 *rx_data,
+ cyg_bool drop_cs)
+{
+ cyg_spi_at91_device_t *at91_spi_dev = (cyg_spi_at91_device_t *) dev;
+
+ // Select the device if not already selected
+ spi_at91_start_transfer(at91_spi_dev);
+
+ // Perform the transfer
+ if (polled)
+ spi_at91_transfer_polled(at91_spi_dev, count, tx_data, rx_data);
+ else
+ spi_at91_transfer(at91_spi_dev, count, tx_data, rx_data);
+
+ // Deselect the device if requested
+ if (drop_cs)
+ spi_at91_drop_cs(at91_spi_dev);
+}
+
+static void
+spi_at91_transaction_tick(cyg_spi_device *dev,
+ cyg_bool polled,
+ cyg_uint32 count)
+{
+ const cyg_uint32 zeros[10] = { 0,0,0,0,0,0,0,0,0,0 };
+
+ cyg_spi_at91_device_t *at91_spi_dev = (cyg_spi_at91_device_t *) dev;
+
+ // Transfer count zeros to the device - we don't touch the
+ // chip select, the device could be selected or deselected.
+ // It is up to the device driver to decide in wich state the
+ // device will be ticked.
+
+ while (count > 0)
+ {
+ int tcnt = count > 40 ? 40 : count;
+
+ if (polled)
+ spi_at91_transfer_polled(at91_spi_dev, tcnt,
+ (const cyg_uint8 *) zeros, NULL);
+ else
+ spi_at91_transfer(at91_spi_dev, tcnt,
+ (const cyg_uint8 *) zeros, NULL);
+
+ count -= tcnt;
+ }
+}
+
+static void
+spi_at91_transaction_end(cyg_spi_device* dev)
+{
+ cyg_spi_at91_device_t * at91_spi_dev = (cyg_spi_at91_device_t *)dev;
+ cyg_spi_at91_bus_t *spi_bus =
+ (cyg_spi_at91_bus_t *)at91_spi_dev->spi_device.spi_bus;
+
+ // Disable the SPI controller
+ HAL_WRITE_UINT32(spi_bus->base+AT91_SPI_CR, AT91_SPI_CR_SPIDIS);
+
+ // Disable SPI clock
+ HAL_WRITE_UINT32(AT91_PMC+AT91_PMC_PCDR,1<<spi_bus->interrupt_number);
+
+ spi_at91_drop_cs((cyg_spi_at91_device_t *) dev);
+}
+
+static int
+spi_at91_get_config(cyg_spi_device *dev,
+ cyg_uint32 key,
+ void *buf,
+ cyg_uint32 *len)
+{
+ cyg_spi_at91_device_t *at91_spi_dev = (cyg_spi_at91_device_t *) dev;
+
+ switch (key)
+ {
+ case CYG_IO_GET_CONFIG_SPI_CLOCKRATE:
+ {
+ if (*len != sizeof(cyg_uint32))
+ return -EINVAL;
+ else
+ {
+ cyg_uint32 *cl_brate = (cyg_uint32 *)buf;
+ *cl_brate = at91_spi_dev->cl_brate;
+ }
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+ return ENOERR;
+}
+
+static int
+spi_at91_set_config(cyg_spi_device *dev,
+ cyg_uint32 key,
+ const void *buf,
+ cyg_uint32 *len)
+{
+ cyg_spi_at91_device_t *at91_spi_dev = (cyg_spi_at91_device_t *) dev;
+
+ switch (key)
+ {
+ case CYG_IO_SET_CONFIG_SPI_CLOCKRATE:
+ {
+ if (*len != sizeof(cyg_uint32))
+ return -EINVAL;
+ else
+ {
+ cyg_uint32 cl_brate = *((cyg_uint32 *)buf);
+ cyg_uint32 old_cl_brate = at91_spi_dev->cl_brate;
+
+ at91_spi_dev->cl_brate = cl_brate;
+
+ if (!spi_at91_calc_scbr(at91_spi_dev))
+ {
+ at91_spi_dev->cl_brate = old_cl_brate;
+ spi_at91_calc_scbr(at91_spi_dev);
+ return -EINVAL;
+ }
+ }
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+ return ENOERR;
+}
+
+// -------------------------------------------------------------------------
+// EOF spi_at91.c
diff --git a/ecos/packages/devs/spi/arm/at91/current/src/spi_at91_init.cxx b/ecos/packages/devs/spi/arm/at91/current/src/spi_at91_init.cxx
new file mode 100644
index 0000000..b8fc586
--- /dev/null
+++ b/ecos/packages/devs/spi/arm/at91/current/src/spi_at91_init.cxx
@@ -0,0 +1,73 @@
+//==========================================================================
+//
+// spi_at91_init.cxx
+//
+// Atmel AT91 (ARM) SPI bus init
+//
+//==========================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2009 Free Software Foundation, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later
+// version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with eCos; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// As a special exception, if other files instantiate templates or use
+// macros or inline functions from this file, or you compile this file
+// and link it with other works to produce a work based on this file,
+// this file does not by itself cause the resulting work to be covered by
+// the GNU General Public License. However the source code for this file
+// must still be made available in accordance with section (3) of the GNU
+// General Public License v2.
+//
+// This exception does not invalidate any other reasons why a work based
+// on this file might be covered by the GNU General Public License.
+// -------------------------------------------
+// ####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Savin Zlobec <savin@elatec.si>
+// Date: 2004-08-25
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#include <cyg/infra/cyg_type.h>
+
+// This file is not needed if we support CYGBLD_ATTRIB_C_INIT_PRI, as the
+// init happens directly in spi_at91.c then.
+#ifndef CYGBLD_ATTRIB_C_INIT_PRI
+
+// -------------------------------------------------------------------------
+
+externC void cyg_spi_at91_bus_init(void);
+
+class cyg_spi_at91_bus_init_class {
+public:
+ cyg_spi_at91_bus_init_class(void) {
+ cyg_spi_at91_bus_init();
+ }
+};
+
+// -------------------------------------------------------------------------
+
+static cyg_spi_at91_bus_init_class spi_at91_bus_init CYGBLD_ATTRIB_INIT_PRI(CYG_INIT_BUS_SPI);
+
+#endif // ifndef CYGBLD_ATTRIB_C_INIT_PRI
+
+// -------------------------------------------------------------------------
+// EOF spi_at91_init.cxx
diff --git a/ecos/packages/devs/spi/arm/eb55/current/ChangeLog b/ecos/packages/devs/spi/arm/eb55/current/ChangeLog
new file mode 100644
index 0000000..bc7a855
--- /dev/null
+++ b/ecos/packages/devs/spi/arm/eb55/current/ChangeLog
@@ -0,0 +1,50 @@
+2009-02-12 Nick Garnett <nickg@ecoscentric.com>
+
+ * src/spi_eb55.c: Export static structure for dataflash SPI device
+ rather than pointer. The latter cannot be used in the initializer
+ for a dataflash flash driver.
+
+2006-06-01 Andrew Lunn <andrew.lunn@ascom.ch>
+
+ * cdl/spi_eb55.cdl: Updates needed for recent changes to AT91 SPI
+ driver.
+
+2004-08-31 Savin Zlobec <savin@elatec.si>
+
+ * cdl/spi_eb55.cdl:
+ Added a require for 4 to 16 decoder of chip select signals option.
+ * src/spi_eb55.c:
+ Defined time between two transfers.
+
+2004-08-27 Savin Zlobec <savin@elatec.si>
+
+ * cdl/spi_eb55.cdl:
+ * include/spi_eb55.h:
+ * src/spi_eb55.c:
+ Atmel AT91EB55 SPI devices.
+
+
+
+//===========================================================================
+// ####GPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 or (at your option) any
+// later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc., 51 Franklin Street,
+// Fifth Floor, Boston, MA 02110-1301, USA.
+// -------------------------------------------
+// ####GPLCOPYRIGHTEND####
+//===========================================================================
diff --git a/ecos/packages/devs/spi/arm/eb55/current/cdl/spi_eb55.cdl b/ecos/packages/devs/spi/arm/eb55/current/cdl/spi_eb55.cdl
new file mode 100644
index 0000000..9a77825
--- /dev/null
+++ b/ecos/packages/devs/spi/arm/eb55/current/cdl/spi_eb55.cdl
@@ -0,0 +1,97 @@
+# ====================================================================
+#
+# spi_eb55.cdl
+#
+# Atmel AT91EB55 SPI devices configuration data
+#
+# ====================================================================
+## ####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating System.
+## Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+##
+## eCos is free software; you can redistribute it and/or modify it under
+## the terms of the GNU General Public License as published by the Free
+## Software Foundation; either version 2 or (at your option) any later
+## version.
+##
+## eCos is distributed in the hope that it will be useful, but WITHOUT
+## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+## for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with eCos; if not, write to the Free Software Foundation, Inc.,
+## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+##
+## As a special exception, if other files instantiate templates or use
+## macros or inline functions from this file, or you compile this file
+## and link it with other works to produce a work based on this file,
+## this file does not by itself cause the resulting work to be covered by
+## the GNU General Public License. However the source code for this file
+## must still be made available in accordance with section (3) of the GNU
+## General Public License v2.
+##
+## This exception does not invalidate any other reasons why a work based
+## on this file might be covered by the GNU General Public License.
+## -------------------------------------------
+## ####ECOSGPLCOPYRIGHTEND####
+# ====================================================================
+######DESCRIPTIONBEGIN####
+#
+# Author(s): Savin Zlobec <savin@elatec.si>
+# Date: 2004-08-27
+#
+#####DESCRIPTIONEND####
+#
+# ====================================================================
+
+cdl_package CYGPKG_DEVS_SPI_ARM_EB55 {
+ parent CYGPKG_IO_SPI
+ active_if CYGPKG_IO_SPI
+ active_if CYGPKG_DEVS_SPI_ARM_AT91
+ display "Atmel AT91EB55 SPI devices"
+ requires CYGHWR_DEVS_SPI_ARM_AT91_BUS0_PCSDEC
+ hardware
+ include_dir cyg/io
+ compile spi_eb55.c
+
+ define_proc {
+ puts $::cdl_system_header "/***** SPI exported devices begin *****/"
+ puts $::cdl_system_header "#include <cyg/io/spi_eb55.h>"
+ puts $::cdl_system_header "/***** SPI exported devices end *****/"
+ }
+
+ cdl_component CYGPKG_DEVS_SPI_ARM_EB55_OPTIONS {
+ display "Atmel AT91EB55 SPI devices build options"
+ flavor none
+ description "
+ Package specific build options including control over
+ compiler flags used only in building this package,
+ and details of which tests are built."
+
+ cdl_option CYGPKG_DEVS_SPI_ARM_EB55_CFLAGS_ADD {
+ display "Additional compiler flags"
+ flavor data
+ no_define
+ default_value { "" }
+ description "
+ This option modifies the set of compiler flags for
+ building the SPI device. These flags are used in addition
+ to the set of global flags."
+ }
+
+ cdl_option CYGPKG_DEVS_SPI_ARM_EB55_CFLAGS_REMOVE {
+ display "Suppressed compiler flags"
+ flavor data
+ no_define
+ default_value { "" }
+ description "
+ This option modifies the set of compiler flags for
+ building the SPI device. These flags are removed from
+ the set of global flags if present."
+ }
+ }
+}
+
+# EOF spi_eb55.cdl
diff --git a/ecos/packages/devs/spi/arm/eb55/current/include/spi_eb55.h b/ecos/packages/devs/spi/arm/eb55/current/include/spi_eb55.h
new file mode 100644
index 0000000..d5df99f
--- /dev/null
+++ b/ecos/packages/devs/spi/arm/eb55/current/include/spi_eb55.h
@@ -0,0 +1,62 @@
+#ifndef CYGONCE_DEVS_SPI_ARM_EB55_H
+#define CYGONCE_DEVS_SPI_ARM_EB55_H
+//==========================================================================
+//
+// spi_eb55.h
+//
+// Atmel AT91EB55 SPI devices defines
+//
+//==========================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later
+// version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with eCos; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// As a special exception, if other files instantiate templates or use
+// macros or inline functions from this file, or you compile this file
+// and link it with other works to produce a work based on this file,
+// this file does not by itself cause the resulting work to be covered by
+// the GNU General Public License. However the source code for this file
+// must still be made available in accordance with section (3) of the GNU
+// General Public License v2.
+//
+// This exception does not invalidate any other reasons why a work based
+// on this file might be covered by the GNU General Public License.
+// -------------------------------------------
+// ####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Savin Zlobec <savin@elatec.si>
+// Date: 2004-08-27
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+//-----------------------------------------------------------------------------
+// AT91EB55 SPI exported devices
+
+#define HAL_SPI_EXPORTED_DEVICES \
+ externC cyg_spi_device *cyg_spi_dataflash_dev0;
+
+//-----------------------------------------------------------------------------
+
+#endif // CYGONCE_DEVS_SPI_ARM_EB55_H
+
+//-----------------------------------------------------------------------------
+// End of spi_eb55.h
diff --git a/ecos/packages/devs/spi/arm/eb55/current/src/spi_eb55.c b/ecos/packages/devs/spi/arm/eb55/current/src/spi_eb55.c
new file mode 100644
index 0000000..81772b5
--- /dev/null
+++ b/ecos/packages/devs/spi/arm/eb55/current/src/spi_eb55.c
@@ -0,0 +1,74 @@
+//==========================================================================
+//
+// spi_eb55.c
+//
+// Atmel AT91EB55 SPI devices
+//
+//==========================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later
+// version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with eCos; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// As a special exception, if other files instantiate templates or use
+// macros or inline functions from this file, or you compile this file
+// and link it with other works to produce a work based on this file,
+// this file does not by itself cause the resulting work to be covered by
+// the GNU General Public License. However the source code for this file
+// must still be made available in accordance with section (3) of the GNU
+// General Public License v2.
+//
+// This exception does not invalidate any other reasons why a work based
+// on this file might be covered by the GNU General Public License.
+// -------------------------------------------
+// ####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Savin Zlobec <savin@elatec.si>
+// Date: 2004-08-27
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#include <pkgconf/hal.h>
+#include <pkgconf/io_spi.h>
+
+#include <cyg/infra/cyg_type.h>
+#include <cyg/io/spi.h>
+#include <cyg/io/spi_at91.h>
+
+// -------------------------------------------------------------------------
+// AT91EB55 SPI exported devices
+
+// AT45DB321B DataFlash
+cyg_spi_at91_device_t spi_dataflash_dev0 CYG_SPI_DEVICE_ON_BUS(0) =
+{
+ .spi_device.spi_bus = &cyg_spi_at91_bus.spi_bus,
+
+ .dev_num = 0, // Device number
+ .cl_pol = 1, // Clock polarity (0 or 1)
+ .cl_pha = 0, // Clock phase (0 or 1)
+ .cl_brate = 8192000, // Clock baud rate
+ .cs_up_udly = 1, // Delay in usec between CS up and transfer start
+ .cs_dw_udly = 1, // Delay in usec between transfer end and CS down
+ .tr_bt_udly = 1 // Delay in usec between two transfers
+};
+
+// -------------------------------------------------------------------------
+// EOF spi_eb55.c
diff --git a/ecos/packages/devs/spi/arm/lpc2xxx/current/ChangeLog b/ecos/packages/devs/spi/arm/lpc2xxx/current/ChangeLog
new file mode 100644
index 0000000..df50e0f
--- /dev/null
+++ b/ecos/packages/devs/spi/arm/lpc2xxx/current/ChangeLog
@@ -0,0 +1,45 @@
+2009-02-18 Jonathan Larmour <jifl@eCosCentric.com>
+
+ * cdl/spi_lpc2xxx.cdl: Fix my mistake in below change and make
+ CDL requires match option names.
+
+2009-02-17 Jonathan Larmour <jifl@eCosCentric.com>
+2009-01-27 Sergei Gavrikov <sergei.gavrikov@gmail.com>
+
+ * cdl/spi_lpc2xxx.cdl: Ensure the SPI interrupts are using different
+ priorities: CYGNUM_IO_SPI_ARM_LPC2XXX_SPI{0,1}_INTPRIO entered.
+ * include/spi_lpc2xxx.h: cyg_spi_lpc2xxx_bus_t: spi_prio field added.
+ * src/spi_lpc2xxx.cxx: spi_lpc2xxx_set_config(): fixed copy & paste
+ typo, spi_lpc2xxx_init_bus(): added 'prio' argument to initializer.
+
+2009-02-10 Bart Veer <bartv@ecoscentric.com>
+
+ * src/spi_lpc2xxx.cxx: update init priority.
+
+2007-07-12 Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
+
+ * lpc2xxx: driver for on-chip SPI units
+
+//===========================================================================
+// ####GPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2009 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 or (at your option) any
+// later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc., 51 Franklin Street,
+// Fifth Floor, Boston, MA 02110-1301, USA.
+// -------------------------------------------
+// ####GPLCOPYRIGHTEND####
+//===========================================================================
diff --git a/ecos/packages/devs/spi/arm/lpc2xxx/current/cdl/spi_lpc2xxx.cdl b/ecos/packages/devs/spi/arm/lpc2xxx/current/cdl/spi_lpc2xxx.cdl
new file mode 100644
index 0000000..b802c2b
--- /dev/null
+++ b/ecos/packages/devs/spi/arm/lpc2xxx/current/cdl/spi_lpc2xxx.cdl
@@ -0,0 +1,103 @@
+# ====================================================================
+#
+# spi_lpc2xxx.cdl
+#
+# SPI driver for LPC2xxx
+#
+# ====================================================================
+## ####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating System.
+## Copyright (C) 1998, 1999, 2000, 2001, 2002 ,2009 Free Software Foundation, Inc.
+##
+## eCos is free software; you can redistribute it and/or modify it under
+## the terms of the GNU General Public License as published by the Free
+## Software Foundation; either version 2 or (at your option) any later
+## version.
+##
+## eCos is distributed in the hope that it will be useful, but WITHOUT
+## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+## for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with eCos; if not, write to the Free Software Foundation, Inc.,
+## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+##
+## As a special exception, if other files instantiate templates or use
+## macros or inline functions from this file, or you compile this file
+## and link it with other works to produce a work based on this file,
+## this file does not by itself cause the resulting work to be covered by
+## the GNU General Public License. However the source code for this file
+## must still be made available in accordance with section (3) of the GNU
+## General Public License v2.
+##
+## This exception does not invalidate any other reasons why a work based
+## on this file might be covered by the GNU General Public License.
+## -------------------------------------------
+## ####ECOSGPLCOPYRIGHTEND####
+# ====================================================================
+######DESCRIPTIONBEGIN####
+#
+# Author(s): Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
+# Contributors:
+# Date: 2007-07-12
+#
+#####DESCRIPTIONEND####
+#
+# ====================================================================
+
+cdl_package CYGPKG_DEVS_SPI_ARM_LPC2XXX {
+ display "LPC2xxx SPI driver"
+ requires CYGPKG_HAL_ARM_LPC2XXX
+
+ parent CYGPKG_IO_SPI
+ active_if CYGPKG_IO_SPI
+
+ include_dir cyg/io
+ compile spi_lpc2xxx.cxx
+
+ cdl_component CYGPKG_DEVS_SPI_ARM_LPC2XXX_BUS0 {
+ display "Enable SPI interface 0"
+ flavor bool
+ default_value 1
+ description "The LPC2xxx controllers contain two SPI interfaces.
+ Enable this component to get support for SPI
+ interface 0."
+
+ cdl_option CYGNUM_IO_SPI_ARM_LPC2XXX_BUS0_INTPRIO {
+ display "Interrupt priority of the SPI bus 0 ISR"
+ flavor data
+ legal_values 0 to 15
+ default_value 12
+ requires { is_active(CYGNUM_IO_SPI_ARM_LPC2XXX_BUS1_INTPRIO)
+ implies (CYGNUM_IO_SPI_ARM_LPC2XXX_BUS0_INTPRIO !=
+ CYGNUM_IO_SPI_ARM_LPC2XXX_BUS1_INTPRIO)
+ }
+ description "
+ This option specifies the interrupt priority of the ISR of
+ the SPI bus 0 interrupt in the VIC. Slot 0 has the highest
+ priority and slot 15 the lowest."
+ }
+ }
+
+ cdl_component CYGPKG_DEVS_SPI_ARM_LPC2XXX_BUS1 {
+ display "Enable SPI interface 1"
+ flavor bool
+ default_value 1
+ description "The LPC2xxx controllers contain two SPI interfaces.
+ Enable this component to get support for SPI
+ interface 1."
+
+ cdl_option CYGNUM_IO_SPI_ARM_LPC2XXX_BUS1_INTPRIO {
+ display "Interrupt priority of the SPI bus 1 ISR"
+ flavor data
+ legal_values 0 to 15
+ default_value 13
+ description "
+ This option specifies the interrupt priority of the ISR of
+ the SPI bus 1 interrupt in the VIC. Slot 0 has the highest
+ priority and slot 15 the lowest."
+ }
+ }
+}
diff --git a/ecos/packages/devs/spi/arm/lpc2xxx/current/include/spi_lpc2xxx.h b/ecos/packages/devs/spi/arm/lpc2xxx/current/include/spi_lpc2xxx.h
new file mode 100644
index 0000000..17eee8e
--- /dev/null
+++ b/ecos/packages/devs/spi/arm/lpc2xxx/current/include/spi_lpc2xxx.h
@@ -0,0 +1,108 @@
+#ifndef CYGONCE_DEVS_SPI_ARM_LPC2XXX_H
+#define CYGONCE_DEVS_SPI_ARM_LPC2XXX_H
+
+//==========================================================================
+//
+// spi_lpc2xxx.h
+//
+// SPI driver for LPC2xxx
+//
+//==========================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later
+// version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with eCos; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// As a special exception, if other files instantiate templates or use
+// macros or inline functions from this file, or you compile this file
+// and link it with other works to produce a work based on this file,
+// this file does not by itself cause the resulting work to be covered by
+// the GNU General Public License. However the source code for this file
+// must still be made available in accordance with section (3) of the GNU
+// General Public License v2.
+//
+// This exception does not invalidate any other reasons why a work based
+// on this file might be covered by the GNU General Public License.
+// -------------------------------------------
+// ####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
+// Contributors:
+// Date: 2007-07-12
+// Purpose:
+// Description:
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#include <pkgconf/hal.h>
+#include <pkgconf/io_spi.h>
+#include <pkgconf/devs_spi_arm_lpc2xxx.h>
+
+#include <cyg/infra/cyg_type.h>
+#include <cyg/hal/drv_api.h>
+#include <cyg/io/spi.h>
+
+struct spi_dev {
+ volatile cyg_uint32 spcr;
+ volatile cyg_uint32 spsr;
+ volatile cyg_uint32 spdr;
+ volatile cyg_uint32 spccr;
+ cyg_uint32 d1, d2, d3;
+ volatile cyg_uint32 spint;
+};
+
+typedef struct {
+ cyg_spi_bus spi_bus;
+
+ cyg_interrupt spi_intr;
+ cyg_handle_t spi_hand;
+ cyg_vector_t spi_vect;
+ cyg_priority_t spi_prio;
+ cyg_drv_mutex_t spi_lock;
+ cyg_drv_cond_t spi_wait;
+
+ struct spi_dev *spi_dev;
+
+ volatile cyg_uint32 count;
+ volatile const cyg_uint8 *tx;
+ volatile cyg_uint8 *rx;
+} cyg_spi_lpc2xxx_bus_t;
+
+typedef struct {
+ cyg_spi_device spi_device;
+
+ cyg_uint8 spi_cpha;
+ cyg_uint8 spi_cpol;
+ cyg_uint8 spi_lsbf;
+ cyg_uint32 spi_baud;
+
+ void (*spi_cs)(int);
+} cyg_spi_lpc2xxx_dev_t;
+
+#ifdef CYGPKG_DEVS_SPI_ARM_LPC2XXX_BUS0
+externC cyg_spi_lpc2xxx_bus_t cyg_spi_lpc2xxx_bus0;
+#endif
+
+#ifdef CYGPKG_DEVS_SPI_ARM_LPC2XXX_BUS1
+externC cyg_spi_lpc2xxx_bus_t cyg_spi_lpc2xxx_bus1;
+#endif
+
+#endif
diff --git a/ecos/packages/devs/spi/arm/lpc2xxx/current/src/spi_lpc2xxx.cxx b/ecos/packages/devs/spi/arm/lpc2xxx/current/src/spi_lpc2xxx.cxx
new file mode 100644
index 0000000..e6cc9e1
--- /dev/null
+++ b/ecos/packages/devs/spi/arm/lpc2xxx/current/src/spi_lpc2xxx.cxx
@@ -0,0 +1,367 @@
+//==========================================================================
+//
+// spi_lpc2xxx.cxx
+//
+// SPI driver for LPC2xxx
+//
+//==========================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2009 Free Software Foundation, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later
+// version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with eCos; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// As a special exception, if other files instantiate templates or use
+// macros or inline functions from this file, or you compile this file
+// and link it with other works to produce a work based on this file,
+// this file does not by itself cause the resulting work to be covered by
+// the GNU General Public License. However the source code for this file
+// must still be made available in accordance with section (3) of the GNU
+// General Public License v2.
+//
+// This exception does not invalidate any other reasons why a work based
+// on this file might be covered by the GNU General Public License.
+// -------------------------------------------
+// ####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
+// Contributors:
+// Date: 2007-07-12
+// Purpose:
+// Description:
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#include <pkgconf/hal.h>
+#include <pkgconf/io_spi.h>
+#include <pkgconf/devs_spi_arm_lpc2xxx.h>
+
+#include <cyg/infra/cyg_type.h>
+#include <cyg/infra/cyg_ass.h>
+#include <cyg/hal/hal_io.h>
+#include <cyg/hal/hal_if.h>
+#include <cyg/hal/hal_intr.h>
+#include <cyg/io/spi.h>
+#include <cyg/io/spi_lpc2xxx.h>
+#include <cyg/error/codes.h>
+
+#define SPI_SPCR_SPIE 0x80
+#define SPI_SPCR_LSBF 0x40
+#define SPI_SPCR_MSTR 0x20
+#define SPI_SPCR_CPOL 0x10
+#define SPI_SPCR_CPHA 0x08
+
+#define SPI_SPSR_SPIF 0x80
+#define SPI_SPSR_WCOL 0x40
+#define SPI_SPSR_ROVR 0x20
+#define SPI_SPSR_MODF 0x10
+#define SPI_SPSR_ABRT 0x08
+
+#define SPI_SPINT 0x01
+
+#ifdef CYGPKG_DEVS_SPI_ARM_LPC2XXX_BUS0
+cyg_spi_lpc2xxx_bus_t cyg_spi_lpc2xxx_bus0;
+CYG_SPI_DEFINE_BUS_TABLE(cyg_spi_lpc2xxx_dev_t, 0);
+#endif
+#ifdef CYGPKG_DEVS_SPI_ARM_LPC2XXX_BUS1
+cyg_spi_lpc2xxx_bus_t cyg_spi_lpc2xxx_bus1;
+CYG_SPI_DEFINE_BUS_TABLE(cyg_spi_lpc2xxx_dev_t, 1);
+#endif
+
+/*
+ * Interrupt routine
+ * read & write the next byte until count reaches zero
+ */
+static cyg_uint32
+spi_lpc2xxx_isr(cyg_vector_t vec, cyg_addrword_t data)
+{
+ cyg_spi_lpc2xxx_bus_t *bus = (cyg_spi_lpc2xxx_bus_t *) data;
+ cyg_uint8 tmp;
+
+ tmp = bus->spi_dev->spsr;
+
+ if(tmp & SPI_SPSR_MODF)
+ bus->spi_dev->spcr = bus->spi_dev->spcr | SPI_SPCR_MSTR;
+
+ tmp = bus->spi_dev->spdr;
+
+ if(bus->count) {
+ if(bus->rx)
+ *bus->rx++ = tmp;
+ if(--bus->count) {
+ bus->spi_dev->spint = SPI_SPINT;
+ bus->spi_dev->spdr = bus->tx ? *bus->tx++ : 0;
+ cyg_drv_interrupt_acknowledge(bus->spi_vect);
+ return CYG_ISR_HANDLED;
+ }
+ }
+
+ bus->count = 0;
+ bus->tx = NULL;
+ bus->rx = NULL;
+
+ bus->spi_dev->spint = SPI_SPINT;
+ cyg_drv_interrupt_acknowledge(bus->spi_vect);
+ return CYG_ISR_HANDLED | CYG_ISR_CALL_DSR;
+}
+
+static void
+spi_lpc2xxx_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrword_t data)
+{
+ cyg_drv_cond_signal(&((cyg_spi_lpc2xxx_bus_t *) data)->spi_wait);
+}
+
+
+/*
+ * Configure bus for a specific baud rate
+ */
+static void
+spi_lpc2xxx_baud(cyg_spi_lpc2xxx_bus_t *bus, cyg_uint32 baud)
+{
+ cyg_uint32 ccr = 8;
+
+ if(baud) {
+ ccr = (CYGNUM_HAL_ARM_LPC2XXX_CLOCK_SPEED
+ / CYGNUM_HAL_ARM_LPC2XXX_VPBDIV) / baud;
+ if(((CYGNUM_HAL_ARM_LPC2XXX_CLOCK_SPEED
+ / CYGNUM_HAL_ARM_LPC2XXX_VPBDIV) / ccr) > baud)
+ ccr++;
+ ccr++;
+ ccr &= 0xfe;
+ }
+
+ bus->spi_dev->spccr = ccr < 8 ? 8 : ccr;
+}
+
+/*
+ * get/set configuration
+ */
+static int
+spi_lpc2xxx_get_config(cyg_spi_device *device, cyg_uint32 key, void *buf,
+ cyg_uint32 *len)
+{
+ cyg_spi_lpc2xxx_dev_t *dev = (cyg_spi_lpc2xxx_dev_t *) device;
+
+ switch(key) {
+ case CYG_IO_GET_CONFIG_SPI_CLOCKRATE:
+ if(*len == sizeof(cyg_uint32)) {
+ cyg_uint32 *b = (cyg_uint32 *) buf;
+ *b = dev->spi_baud;
+ } else return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return ENOERR;
+}
+
+static int
+spi_lpc2xxx_set_config(cyg_spi_device *device, cyg_uint32 key, const void *buf,
+ cyg_uint32 *len)
+{
+ cyg_spi_lpc2xxx_dev_t *dev = (cyg_spi_lpc2xxx_dev_t *) device;
+
+ switch(key) {
+ case CYG_IO_SET_CONFIG_SPI_CLOCKRATE:
+ if(*len == sizeof(cyg_uint32)) {
+ dev->spi_baud = * (cyg_uint32 *) buf;
+ spi_lpc2xxx_baud((cyg_spi_lpc2xxx_bus_t *) dev->spi_device.spi_bus,
+ dev->spi_baud);
+ }
+ else return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return ENOERR;
+}
+
+
+/*
+ * Begin transaction
+ * configure bus for device and drive CS by calling device cs() function
+ */
+static void
+spi_lpc2xxx_begin(cyg_spi_device *device)
+{
+ cyg_spi_lpc2xxx_dev_t *dev = (cyg_spi_lpc2xxx_dev_t *) device;
+ cyg_spi_lpc2xxx_bus_t *bus =
+ (cyg_spi_lpc2xxx_bus_t *) dev->spi_device.spi_bus;
+
+ cyg_uint8 cr =
+ (dev->spi_cpha ? SPI_SPCR_CPHA : 0) |
+ (dev->spi_cpol ? SPI_SPCR_CPOL : 0) |
+ (dev->spi_lsbf ? SPI_SPCR_LSBF : 0);
+
+ bus->spi_dev->spcr = SPI_SPCR_MSTR | cr;
+
+ spi_lpc2xxx_baud(bus, dev->spi_baud);
+
+ dev->spi_cs(1);
+}
+
+
+/*
+ * Transfer a buffer to a device,
+ * fill another buffer with data from the device
+ */
+static void
+spi_lpc2xxx_transfer(cyg_spi_device *device, cyg_bool polled, cyg_uint32 count,
+ const cyg_uint8 *tx_data, cyg_uint8 *rx_data,
+ cyg_bool drop_cs)
+{
+ cyg_spi_lpc2xxx_dev_t *dev = (cyg_spi_lpc2xxx_dev_t *) device;
+ cyg_spi_lpc2xxx_bus_t *bus =
+ (cyg_spi_lpc2xxx_bus_t *) dev->spi_device.spi_bus;
+ cyg_uint8 tmp;
+
+ if(!count) return;
+
+ if(!polled) {
+ bus->count = count;
+ bus->tx = tx_data;
+ bus->rx = rx_data;
+
+ bus->spi_dev->spcr |= SPI_SPCR_SPIE;
+ bus->spi_dev->spdr = bus->tx ? *bus->tx++ : 0;
+
+ cyg_drv_mutex_lock(&bus->spi_lock);
+ cyg_drv_dsr_lock();
+ cyg_drv_interrupt_unmask(bus->spi_vect);
+ while(bus->count)
+ cyg_drv_cond_wait(&bus->spi_wait);
+ cyg_drv_interrupt_mask(bus->spi_vect);
+ cyg_drv_dsr_unlock();
+ cyg_drv_mutex_unlock(&bus->spi_lock);
+ } else do {
+ bus->spi_dev->spdr = tx_data ? *tx_data++ : 0;
+ while(!(bus->spi_dev->spsr & SPI_SPSR_SPIF));
+ tmp = bus->spi_dev->spdr;
+ if(rx_data)
+ *rx_data++ = tmp;
+ count--;
+ } while(count);
+
+ if(drop_cs)
+ dev->spi_cs(0);
+
+ return;
+}
+
+
+/*
+ * Tick
+ */
+static void
+spi_lpc2xxx_tick(cyg_spi_device *device, cyg_bool polled, cyg_uint32 count)
+{
+ spi_lpc2xxx_transfer(device, polled, count, NULL, NULL, false);
+}
+
+
+/*
+ * End transaction
+ * disable SPI bus, drop CS, reset transfer variables
+ */
+static void
+spi_lpc2xxx_end(cyg_spi_device *device)
+{
+ cyg_spi_lpc2xxx_dev_t *dev = (cyg_spi_lpc2xxx_dev_t *) device;
+ cyg_spi_lpc2xxx_bus_t *bus =
+ (cyg_spi_lpc2xxx_bus_t *) dev->spi_device.spi_bus;
+
+ bus->spi_dev->spcr = 0;
+ dev->spi_cs(0);
+
+ bus->count = 0;
+ bus->tx = NULL;
+ bus->rx = NULL;
+}
+
+
+/*
+ * Driver & bus initialization
+ */
+static void
+spi_lpc2xxx_init_bus(cyg_spi_lpc2xxx_bus_t *bus,
+ cyg_addrword_t dev,
+ cyg_vector_t vec,
+ cyg_priority_t prio)
+{
+ bus->spi_bus.spi_transaction_begin = spi_lpc2xxx_begin;
+ bus->spi_bus.spi_transaction_transfer = spi_lpc2xxx_transfer;
+ bus->spi_bus.spi_transaction_tick = spi_lpc2xxx_tick;
+ bus->spi_bus.spi_transaction_end = spi_lpc2xxx_end;
+ bus->spi_bus.spi_get_config = spi_lpc2xxx_get_config;
+ bus->spi_bus.spi_set_config = spi_lpc2xxx_set_config;
+ CYG_SPI_BUS_COMMON_INIT(&bus->spi_bus);
+
+ cyg_drv_mutex_init(&bus->spi_lock);
+ cyg_drv_cond_init(&bus->spi_wait, &bus->spi_lock);
+
+ bus->spi_dev = (struct spi_dev *) dev;
+ bus->spi_vect = vec;
+ bus->spi_prio = prio;
+ cyg_drv_interrupt_create(
+ vec, prio, (cyg_addrword_t) bus,
+ &spi_lpc2xxx_isr, &spi_lpc2xxx_dsr,
+ &bus->spi_hand, &bus->spi_intr);
+ cyg_drv_interrupt_attach(bus->spi_hand);
+}
+
+/*
+ * initialization class
+ */
+class cyg_spi_lpc2xxx_init_class {
+public:
+ cyg_spi_lpc2xxx_init_class(void) {
+ cyg_uint32 addr, tmp;
+
+#ifdef CYGPKG_DEVS_SPI_ARM_LPC2XXX_BUS0
+ addr = (CYGARC_HAL_LPC2XXX_REG_PIN_BASE
+ + CYGARC_HAL_LPC2XXX_REG_PINSEL0);
+ HAL_READ_UINT32(addr, tmp);
+ tmp |= 0x5500;
+ HAL_WRITE_UINT32(addr, tmp);
+
+ spi_lpc2xxx_init_bus(&cyg_spi_lpc2xxx_bus0,
+ CYGARC_HAL_LPC2XXX_REG_SPI0_BASE,
+ CYGNUM_HAL_INTERRUPT_SPI0,
+ CYGNUM_IO_SPI_ARM_LPC2XXX_BUS0_INTPRIO);
+#endif
+#ifdef CYGPKG_DEVS_SPI_ARM_LPC2XXX_BUS1
+ addr = (CYGARC_HAL_LPC2XXX_REG_PIN_BASE
+ + CYGARC_HAL_LPC2XXX_REG_PINSEL1);
+ HAL_READ_UINT32(addr, tmp);
+ tmp |= 0x2a8;
+ HAL_WRITE_UINT32(addr, tmp);
+ spi_lpc2xxx_init_bus(&cyg_spi_lpc2xxx_bus1,
+ CYGARC_HAL_LPC2XXX_REG_SPI1_BASE,
+ CYGNUM_HAL_INTERRUPT_SPI1,
+ CYGNUM_IO_SPI_ARM_LPC2XXX_BUS1_INTPRIO);
+#endif
+ }
+};
+
+static cyg_spi_lpc2xxx_init_class spi_lpc2xxx_init
+ CYGBLD_ATTRIB_INIT_PRI(CYG_INIT_BUS_SPI);
+
diff --git a/ecos/packages/devs/spi/cortexm/a2fxxx/current/ChangeLog b/ecos/packages/devs/spi/cortexm/a2fxxx/current/ChangeLog
new file mode 100644
index 0000000..80da248
--- /dev/null
+++ b/ecos/packages/devs/spi/cortexm/a2fxxx/current/ChangeLog
@@ -0,0 +1,35 @@
+2012-01-04 Christophe Coutand <ecos@hotmail.co.uk>
+ * src/spi_a2fxxx.c:
+ Fix compiler warning, used uninitialized variable in a2fxxx_spi_set_ss().
+
+2011-04-13 Christophe Coutand <ecos@hotmail.co.uk>
+
+ * cdl/spi_a2fxxx.cdl:
+ * include/spi_a2fxxx.h:
+ * src/spi_a2fxxx.c:
+ New package -- Smartfusion Cortex-M3 SPI driver package.
+ [Bugzilla 1001291]
+
+//===========================================================================
+// ####GPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 or (at your option) any
+// later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc., 51 Franklin Street,
+// Fifth Floor, Boston, MA 02110-1301, USA.
+// -------------------------------------------
+// ####GPLCOPYRIGHTEND####
+//===========================================================================
diff --git a/ecos/packages/devs/spi/cortexm/a2fxxx/current/cdl/spi_a2fxxx.cdl b/ecos/packages/devs/spi/cortexm/a2fxxx/current/cdl/spi_a2fxxx.cdl
new file mode 100644
index 0000000..8d16000
--- /dev/null
+++ b/ecos/packages/devs/spi/cortexm/a2fxxx/current/cdl/spi_a2fxxx.cdl
@@ -0,0 +1,175 @@
+##=============================================================================
+##
+## spi_a2fxxx.cdl
+##
+## Smartfusion Cortex-M3 SPI driver configuration options.
+##
+##=============================================================================
+## ####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating System.
+## Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc.
+##
+## eCos is free software; you can redistribute it and/or modify it under
+## the terms of the GNU General Public License as published by the Free
+## Software Foundation; either version 2 or (at your option) any later
+## version.
+##
+## eCos is distributed in the hope that it will be useful, but WITHOUT
+## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+## for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with eCos; if not, write to the Free Software Foundation, Inc.,
+## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+##
+## As a special exception, if other files instantiate templates or use
+## macros or inline functions from this file, or you compile this file
+## and link it with other works to produce a work based on this file,
+## this file does not by itself cause the resulting work to be covered by
+## the GNU General Public License. However the source code for this file
+## must still be made available in accordance with section (3) of the GNU
+## General Public License v2.
+##
+## This exception does not invalidate any other reasons why a work based
+## on this file might be covered by the GNU General Public License.
+## -------------------------------------------
+## ####ECOSGPLCOPYRIGHTEND####
+##=============================================================================
+#######DESCRIPTIONBEGIN####
+##
+## Author(s): ccoutand, updated for Smartfusion Cortex-M3
+## Original(s): Chris Holgate
+## Date: 2011-04-25
+## Purpose: Configure Smartfusion Cortex-M3 SPI driver.
+##
+######DESCRIPTIONEND####
+##
+##=============================================================================
+
+cdl_package CYGPKG_DEVS_SPI_CORTEXM_A2FXXX {
+ display "Actel Smartfusion SPI driver"
+ description "
+ This package provides SPI driver support for the Smartfusion Cortex-M3
+ series of microcontrollers.
+ "
+ parent CYGPKG_IO_SPI
+ active_if CYGPKG_IO_SPI
+ requires CYGPKG_HAL_CORTEXM_A2FXXX
+ hardware
+ include_dir cyg/io
+ compile -library=libextras.a spi_a2fxxx.c
+
+ cdl_option CYGDBG_DEVS_SPI_CORTEXM_A2FXXX_TRACE {
+ display "Display status messages during SPI operations"
+ flavor bool
+ default_value 0
+ description "
+ Selecting this option will cause the SPI driver to print status
+ messages as various SPI operations are undertaken."
+ }
+
+ cdl_component CYGHWR_DEVS_SPI_CORTEXM_A2FXXX_BUS1 {
+ display "Actel Smartfusion SPI bus 1"
+ description "
+ Enable SPI bus 1 on the A2FXXX device.
+ "
+ flavor bool
+ default_value false
+
+ cdl_option CYGNUM_DEVS_SPI_CORTEXM_A2FXXX_BUS1_TX_DMA {
+ display "Transmit DMA channel number"
+ flavor data
+ default_value 0
+ }
+
+ cdl_option CYGNUM_DEVS_SPI_CORTEXM_A2FXXX_BUS1_RX_DMA {
+ display "Receive DMA channel number"
+ flavor data
+ default_value 1
+ }
+
+ cdl_option CYGDAT_DEVS_SPI_CORTEXM_A2FXXX_BUS1_TX_DMA_PRI {
+ display "Transmit DMA channel priority"
+ legal_values { "HIGH" "LOW" }
+ flavor data
+ default_value { "HIGH" }
+ }
+
+ cdl_option CYGDAT_DEVS_SPI_CORTEXM_A2FXXX_BUS1_RX_DMA_PRI {
+ display "Receive DMA channel priority"
+ legal_values { "HIGH" "LOW" }
+ flavor data
+ default_value { "HIGH" }
+ }
+ }
+
+ cdl_component CYGHWR_DEVS_SPI_CORTEXM_A2FXXX_BUS2 {
+ display "Actel Smartfusion SPI bus 2"
+ description "
+ Enable SPI bus 2 on the A2FXXX device.
+ "
+ flavor bool
+ default_value false
+
+ cdl_option CYGNUM_DEVS_SPI_CORTEXM_A2FXXX_BUS2_TX_DMA {
+ display "Transmit DMA channel number"
+ flavor data
+ default_value 2
+ }
+
+ cdl_option CYGNUM_DEVS_SPI_CORTEXM_A2FXXX_BUS2_RX_DMA {
+ display "Receive DMA channel number"
+ flavor data
+ default_value 3
+ }
+
+ cdl_option CYGDAT_DEVS_SPI_CORTEXM_A2FXXX_BUS2_TX_DMA_PRI {
+ display "Transmit DMA channel priority"
+ legal_values { "HIGH" "LOW" }
+ flavor data
+ default_value { "HIGH" }
+ }
+
+ cdl_option CYGDAT_DEVS_SPI_CORTEXM_A2FXXX_BUS2_RX_DMA_PRI {
+ display "Receive DMA channel priority"
+ legal_values { "HIGH" "LOW" }
+ flavor data
+ default_value { "HIGH" }
+ }
+ }
+
+ cdl_component CYGPKG_DEVS_SPI_CORTEXM_A2FXXX_OPTIONS {
+ display "Actel Smartfusion SPI driver build options"
+ flavor none
+ description "
+ Package specific build options including control over
+ compiler flags used only in building this package,
+ and details of which tests are built."
+
+ cdl_option CYGPKG_DEVS_SPI_CORTEXM_A2FXXX_CFLAGS_ADD {
+ display "Additional compiler flags"
+ flavor data
+ no_define
+ default_value { "" }
+ description "
+ This option modifies the set of compiler flags for
+ building the A2FXXX SPI driver. These flags are used in addition
+ to the set of global flags."
+ }
+
+ cdl_option CYGPKG_DEVS_SPI_CORTEXM_A2FXXX_CFLAGS_REMOVE {
+ display "Suppressed compiler flags"
+ flavor data
+ no_define
+ default_value { "" }
+ description "
+ This option modifies the set of compiler flags for
+ building the A2FXXX SPI driver. These flags are removed from
+ the set of global flags if present."
+ }
+ }
+
+}
+# EOF spi_a2fxxx.cdl
diff --git a/ecos/packages/devs/spi/cortexm/a2fxxx/current/include/spi_a2fxxx.h b/ecos/packages/devs/spi/cortexm/a2fxxx/current/include/spi_a2fxxx.h
new file mode 100644
index 0000000..a871b9a
--- /dev/null
+++ b/ecos/packages/devs/spi/cortexm/a2fxxx/current/include/spi_a2fxxx.h
@@ -0,0 +1,195 @@
+#ifndef CYGONCE_DEVS_SPI_CORTEXM_STM32_H
+# define CYGONCE_DEVS_SPI_CORTEXM_STM32_H
+//=============================================================================
+//
+// spi_a2fxxx.h
+//
+// Header definitions for Smartfusion Cortex-M3 SPI driver.
+//
+//=============================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later
+// version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with eCos; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// As a special exception, if other files instantiate templates or use
+// macros or inline functions from this file, or you compile this file
+// and link it with other works to produce a work based on this file,
+// this file does not by itself cause the resulting work to be covered by
+// the GNU General Public License. However the source code for this file
+// must still be made available in accordance with section (3) of the GNU
+// General Public License v2.
+//
+// This exception does not invalidate any other reasons why a work based
+// on this file might be covered by the GNU General Public License.
+// -------------------------------------------
+// ####ECOSGPLCOPYRIGHTEND####
+//=============================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): ccoutand, updated for Smartfusion Cortex-M3
+// Original(s): Chris Holgate
+// Date: 2011-04-25
+// Purpose: Smartfusion Cortex-M3 SPI driver definitions.
+// Description:
+// Usage: #include <cyg/io/spi_a2fxxx.h>
+//
+//####DESCRIPTIONEND####
+//
+//=============================================================================
+
+# include <pkgconf/hal.h>
+# include <pkgconf/io_spi.h>
+# include <pkgconf/devs_spi_cortexm_a2fxxx.h>
+
+# include <cyg/infra/cyg_type.h>
+# include <cyg/hal/drv_api.h>
+# include <cyg/io/spi.h>
+
+__externC cyg_uint32 a2fxxx_dma_ch_attach(cyg_uint8, cyg_ISR_t *, cyg_DSR_t *,
+ cyg_addrword_t);
+
+typedef enum a2fxxx_spi_mode {
+ A2FXXX_SPI_MOTOROLA = 0x00,
+ A2FXXX_SPI_TI_SYNC_SERIAL = 0x01,
+ A2FXXX_SPI_NS_MICROWIRE = 0x02
+} a2fxxx_spi_mode;
+
+//-----------------------------------------------------------------------------
+// Macro for defining a SPI device and attaching it to the appropriate bus.
+//
+// _name_ is the name of the SPI device. This will be used to reference a
+// data structure of type cyg_spi_device which can be passed to the
+// SPI driver API without needing a cast.
+// _bus_ is the bus number to which this device is attached (1, 2 or 3).
+// _csnum_ when _csgpio_ is set to false : is the chip select line used for
+// this device, numbered from 0.
+// when _csgpio_ is set to true : is the GPIO number used to drive the
+// device chip select line.
+// _csgpio_ when set to false, the device chip select line is controlled by the
+// SPI controller.
+// when set to true, the device chip select line is a GPIO of the processor
+// control by the SPI driver.
+// _proto_ is the SPI bus protocol:
+// 0 -> Motorola SPI Protocol (_clpol_ and _clpha_ are valid in this mode)
+// 1 -> National Semiconductor MICROWIRE Protocol
+// 2 -> Texas Instruments (TI) Synchronous Serial Protocol
+// _clpol_ is the SPI bus clock polarity used by the device. This must be
+// set to 1 if a clock line pullup resistor is used and 0 if a
+// clock line pulldown resistor is used.
+// _clpha_ is the SPI bus clock phase used by the device.
+// _brate_ is the SPI bus clock baud rate used by the device, measured in Hz.
+// _csup_dly_ is the minimum delay between chip select assert and transfer
+// start, measured in microseconds.
+// _csdw_dly_ is the minimum delay between transfer end and chip select deassert,
+// measured in microseconds.
+// _trbt_dly_ is the minimum delay between consecutive transfers.
+
+# define CYG_DEVS_SPI_CORTEXM_A2FXXX_DEVICE( \
+ _name_, _bus_, _csnum_, _csgpio_, _proto_, _clpol_, _clpha_, _brate_, _csup_dly_, _csdw_dly_, _trbt_dly_\
+) \
+cyg_spi_cortexm_a2fxxx_device_t _name_ ##_a2fxxx CYG_SPI_DEVICE_ON_BUS(_bus_) = { \
+{ .spi_bus = (cyg_spi_bus*) &cyg_spi_a2fxxx_bus## _bus_ }, \
+ .dev_num = _csnum_, \
+ .cs_gpio = _csgpio_, \
+ .cs_gpio_n = _csnum_, \
+ .proto = _proto_, \
+ .cl_pol = _clpol_, \
+ .cl_pha = _clpha_, \
+ .cl_brate = _brate_, \
+ .cs_up_udly = _csup_dly_, \
+ .cs_dw_udly = _csdw_dly_, \
+ .tr_bt_udly = _trbt_dly_, \
+ .spi_cr_val = 0, \
+}; \
+extern cyg_spi_device _name_ __attribute__((alias ( #_name_ "_a2fxxx" )));
+
+//-----------------------------------------------------------------------------
+// A2FXXX SPI bus configuration and state.
+
+typedef struct cyg_spi_cortexm_a2fxxx_bus_setup_s {
+ cyg_uint32 apb_freq; // Peripheral bus frequency (fp).
+ cyg_haladdress spi_reg_base; // Base address of SPI register block.
+ cyg_haladdress dma_reg_base; // Base address of DMA register block.
+ cyg_uint8 dma_tx_channel; // TX DMA channel for this bus.
+ cyg_uint8 dma_rx_channel; // RX DMA channel for this bus.
+ cyg_uint8 cs_gpio_num; // Number of chip selects for this bus.
+ const cyg_uint8 *cs_gpio_list; // List of GPIOs used as chip selects.
+ const cyg_uint8 *spi_gpio_list; // List of GPIOs used by the SPI interface.
+ cyg_bool dma_tx_pri; // Priority for DMA transmit.
+ cyg_bool dma_rx_pri; // Priority for DMA receive.
+ cyg_haladdress *rx_dma_null;
+ cyg_haladdress *tx_dma_null;
+} cyg_spi_cortexm_a2fxxx_bus_setup_t;
+
+typedef struct cyg_spi_cortexm_a2fxxx_bus_s {
+ // ---- Upper layer data ----
+ cyg_spi_bus spi_bus; // Upper layer SPI bus data.
+
+ // ---- Bus configuration constants ----
+ const cyg_spi_cortexm_a2fxxx_bus_setup_t *setup;
+
+ // ---- Driver state (private) ----
+ cyg_interrupt tx_intr_data; // DMA interrupt data (TX).
+ cyg_interrupt rx_intr_data; // DMA interrupt data (RX).
+ cyg_handle_t tx_intr_handle; // DMA interrupt handle (TX).
+ cyg_handle_t rx_intr_handle; // DMA interrupt handle (RX).
+ cyg_drv_mutex_t mutex; // Transfer mutex.
+ cyg_drv_cond_t condvar; // Transfer condition variable.
+ cyg_bool tx_dma_done; // Flags used to signal completion.
+ cyg_bool rx_dma_done; // Flags used to signal completion.
+ cyg_bool cs_up; // Chip select asserted flag.
+
+} cyg_spi_cortexm_a2fxxx_bus_t;
+
+//-----------------------------------------------------------------------------
+// A2FXXX SPI device.
+
+typedef struct cyg_spi_cortexm_a2fxxx_device_s {
+ // ---- Upper layer data ----
+ cyg_spi_device spi_device; // Upper layer SPI device data.
+
+ // ---- Device setup (user configurable) ----
+ cyg_uint8 dev_num; // Device number.
+ a2fxxx_spi_mode proto; // Protocol
+ cyg_bool cs_gpio; // True = use GPIO to control CS line
+ cyg_uint32 cs_gpio_n; // GPIO #
+ cyg_uint8 cl_pol; // Clock polarity (0 or 1).
+ cyg_uint8 cl_pha; // Clock phase (0 or 1).
+ cyg_uint32 cl_brate; // Clock baud rate.
+ cyg_uint16 cs_up_udly; // Minimum delay in us between CS up and transfer start.
+ cyg_uint16 cs_dw_udly; // Minimum delay in us between transfer end and CS down.
+ cyg_uint16 tr_bt_udly; // Minimum delay in us between two transfers.
+
+ // ---- Device state (private) ----
+ cyg_uint32 spi_cr_val; // SPI configuration register (initialised to 0).
+
+} cyg_spi_cortexm_a2fxxx_device_t;
+
+//-----------------------------------------------------------------------------
+// Exported bus data structures.
+
+# ifdef CYGHWR_DEVS_SPI_CORTEXM_A2FXXX_BUS1
+externC cyg_spi_cortexm_a2fxxx_bus_t cyg_spi_a2fxxx_bus1;
+# endif
+
+# ifdef CYGHWR_DEVS_SPI_CORTEXM_A2FXXX_BUS2
+externC cyg_spi_cortexm_a2fxxx_bus_t cyg_spi_a2fxxx_bus2;
+# endif
+
+//=============================================================================
+#endif // CYGONCE_DEVS_SPI_CORTEXM_A2FXXX_H
diff --git a/ecos/packages/devs/spi/cortexm/a2fxxx/current/src/spi_a2fxxx.c b/ecos/packages/devs/spi/cortexm/a2fxxx/current/src/spi_a2fxxx.c
new file mode 100644
index 0000000..3459fdc
--- /dev/null
+++ b/ecos/packages/devs/spi/cortexm/a2fxxx/current/src/spi_a2fxxx.c
@@ -0,0 +1,638 @@
+//=============================================================================
+//
+// spi_a2fxxx.c
+//
+// SPI driver implementation for Smartfusion Cortex-M3
+//
+//=============================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later
+// version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with eCos; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// As a special exception, if other files instantiate templates or use
+// macros or inline functions from this file, or you compile this file
+// and link it with other works to produce a work based on this file,
+// this file does not by itself cause the resulting work to be covered by
+// the GNU General Public License. However the source code for this file
+// must still be made available in accordance with section (3) of the GNU
+// General Public License v2.
+//
+// This exception does not invalidate any other reasons why a work based
+// on this file might be covered by the GNU General Public License.
+// -------------------------------------------
+// ####ECOSGPLCOPYRIGHTEND####
+//=============================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): ccoutand, updated for Smartfusion Cortex-M3
+// Original(s): Chris Holgate
+// Date: 2011-04-25
+// Purpose: Smartfusion Cortex-M3 SPI driver implementation
+//
+//####DESCRIPTIONEND####
+//
+//=============================================================================
+
+#include <cyg/hal/hal_io.h>
+#include <cyg/hal/hal_if.h>
+#include <cyg/hal/hal_intr.h>
+#include <cyg/hal/drv_api.h>
+
+#include <cyg/infra/cyg_type.h>
+#include <cyg/infra/cyg_ass.h>
+#include <cyg/infra/diag.h>
+
+#include <cyg/io/spi.h>
+#include <cyg/io/spi_a2fxxx.h>
+
+#include <pkgconf/devs_spi_cortexm_a2fxxx.h>
+
+#include <string.h>
+
+#if defined(CYGHWR_DEVS_SPI_CORTEXM_A2FXXX_BUS1) || \
+ defined(CYGHWR_DEVS_SPI_CORTEXM_A2FXXX_BUS2)
+
+#ifdef CYGDBG_DEVS_SPI_CORTEXM_A2FXXX_TRACE
+# define SPI_TRACE(args...) diag_printf(args)
+#else
+# define SPI_TRACE(args...)
+#endif
+
+//-----------------------------------------------------------------------------
+// API function call forward references.
+
+static void a2fxxx_transaction_begin (cyg_spi_device*);
+static void a2fxxx_transaction_transfer (cyg_spi_device*, cyg_bool, cyg_uint32, const cyg_uint8*, cyg_uint8*, cyg_bool);
+static void a2fxxx_transaction_tick (cyg_spi_device*, cyg_bool, cyg_uint32);
+static void a2fxxx_transaction_end (cyg_spi_device*);
+static int a2fxxx_get_config (cyg_spi_device*, cyg_uint32, void*, cyg_uint32*);
+static int a2fxxx_set_config (cyg_spi_device*, cyg_uint32, const void*, cyg_uint32*);
+
+//-----------------------------------------------------------------------------
+// Instantiate the bus state data structures.
+
+#ifdef CYGHWR_DEVS_SPI_CORTEXM_A2FXXX_BUS1
+
+static cyg_haladdress rx1_dma_null = 0x0;
+static cyg_haladdress tx1_dma_null = 0x0;
+
+static const cyg_spi_cortexm_a2fxxx_bus_setup_t bus1_setup = {
+ .spi_reg_base = CYGHWR_HAL_A2FXXX_SPI0,
+ .dma_reg_base = CYGHWR_HAL_A2FXXX_DMA,
+ .dma_tx_channel = CYGNUM_DEVS_SPI_CORTEXM_A2FXXX_BUS1_TX_DMA,
+ .dma_rx_channel = CYGNUM_DEVS_SPI_CORTEXM_A2FXXX_BUS1_RX_DMA,
+#ifdef CYGDAT_DEVS_SPI_CORTEXM_A2FXXX_BUS1_TX_DMA_PRI_HIGH
+ .dma_tx_pri = true,
+#else
+ .dma_tx_pri = false,
+#endif
+#ifdef CYGDAT_DEVS_SPI_CORTEXM_A2FXXX_BUS1_RX_DMA_PRI_HIGH
+ .dma_rx_pri = true,
+#else
+ .dma_rx_pri = false,
+#endif
+ .rx_dma_null = &rx1_dma_null,
+ .tx_dma_null = &tx1_dma_null,
+};
+
+cyg_spi_cortexm_a2fxxx_bus_t cyg_spi_a2fxxx_bus1 = {
+ .spi_bus.spi_transaction_begin = a2fxxx_transaction_begin,
+ .spi_bus.spi_transaction_transfer = a2fxxx_transaction_transfer,
+ .spi_bus.spi_transaction_tick = a2fxxx_transaction_tick,
+ .spi_bus.spi_transaction_end = a2fxxx_transaction_end,
+ .spi_bus.spi_get_config = a2fxxx_get_config,
+ .spi_bus.spi_set_config = a2fxxx_set_config,
+ .setup = &bus1_setup,
+ .cs_up = false
+};
+#endif
+
+#ifdef CYGHWR_DEVS_SPI_CORTEXM_A2FXXX_BUS2
+
+static cyg_haladdress rx2_dma_null = 0x0;
+static cyg_haladdress tx2_dma_null = 0x0;
+
+static const cyg_spi_cortexm_a2fxxx_bus_setup_t bus2_setup = {
+ .spi_reg_base = CYGHWR_HAL_A2FXXX_SPI1,
+ .dma_reg_base = CYGHWR_HAL_A2FXXX_DMA,
+ .dma_tx_channel = CYGNUM_DEVS_SPI_CORTEXM_A2FXXX_BUS2_TX_DMA,
+ .dma_rx_channel = CYGNUM_DEVS_SPI_CORTEXM_A2FXXX_BUS2_RX_DMA,
+#ifdef CYGDAT_DEVS_SPI_CORTEXM_A2FXXX_BUS2_TX_DMA_PRI_HIGH
+ .dma_tx_pri = true,
+#else
+ .dma_tx_pri = false,
+#endif
+#ifdef CYGDAT_DEVS_SPI_CORTEXM_A2FXXX_BUS2_RX_DMA_PRI_HIGH
+ .dma_rx_pri = true,
+#else
+ .dma_rx_pri = false,
+#endif
+ .rx_dma_null = &rx2_dma_null,
+ .tx_dma_null = &tx2_dma_null,
+};
+
+cyg_spi_cortexm_a2fxxx_bus_t cyg_spi_a2fxxx_bus2 = {
+ .spi_bus.spi_transaction_begin = a2fxxx_transaction_begin,
+ .spi_bus.spi_transaction_transfer = a2fxxx_transaction_transfer,
+ .spi_bus.spi_transaction_tick = a2fxxx_transaction_tick,
+ .spi_bus.spi_transaction_end = a2fxxx_transaction_end,
+ .spi_bus.spi_get_config = a2fxxx_get_config,
+ .spi_bus.spi_set_config = a2fxxx_set_config,
+ .setup = &bus2_setup,
+ .cs_up = false
+};
+#endif
+
+
+//-----------------------------------------------------------------------------
+// Implement DMA ISRs. These clear the DMA channel interrupts and
+// schedule their respective DSRs.
+
+static cyg_uint32 a2fxxx_tx_ISR
+ (cyg_vector_t vector, cyg_addrword_t data)
+{
+ cyg_spi_cortexm_a2fxxx_bus_t* a2fxxx_bus =
+ (cyg_spi_cortexm_a2fxxx_bus_t*) data;
+ cyg_uint8 chan = a2fxxx_bus->setup->dma_tx_channel;
+ SPI_TRACE("SPI : Handle TX ISR\n");
+ a2fxxx_dma_clear_interrupt ( chan );
+ return (CYG_ISR_CALL_DSR | CYG_ISR_HANDLED);
+}
+
+static cyg_uint32 a2fxxx_rx_ISR
+ (cyg_vector_t vector, cyg_addrword_t data)
+{
+ cyg_spi_cortexm_a2fxxx_bus_t* a2fxxx_bus =
+ (cyg_spi_cortexm_a2fxxx_bus_t*) data;
+ cyg_uint8 chan = a2fxxx_bus->setup->dma_rx_channel;
+ SPI_TRACE("SPI : Handle RX ISR\n");
+ a2fxxx_dma_clear_interrupt ( chan );
+ return (CYG_ISR_CALL_DSR | CYG_ISR_HANDLED);
+}
+
+//-----------------------------------------------------------------------------
+// Implement DMA DSRs. These clear down the interrupt conditions and assert
+// their respective 'transaction complete' flags.
+
+static void a2fxxx_tx_DSR
+ (cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
+{
+ cyg_spi_cortexm_a2fxxx_bus_t* a2fxxx_bus =
+ (cyg_spi_cortexm_a2fxxx_bus_t*) data;
+ SPI_TRACE("SPI : Handle TX DSR\n");
+ cyg_drv_dsr_lock ();
+ a2fxxx_bus->tx_dma_done = true;
+ cyg_drv_cond_signal (&a2fxxx_bus->condvar);
+ cyg_drv_dsr_unlock ();
+}
+
+static void a2fxxx_rx_DSR
+ (cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
+{
+ cyg_spi_cortexm_a2fxxx_bus_t* a2fxxx_bus =
+ (cyg_spi_cortexm_a2fxxx_bus_t*) data;
+ SPI_TRACE("SPI : Handle RX DSR\n");
+ cyg_drv_dsr_lock ();
+ a2fxxx_bus->rx_dma_done = true;
+ cyg_drv_cond_signal (&a2fxxx_bus->condvar);
+ cyg_drv_dsr_unlock ();
+}
+
+//-----------------------------------------------------------------------------
+// Set up a new SPI bus on initialization.
+
+static void a2fxxx_spi_bus_setup
+ (cyg_spi_cortexm_a2fxxx_bus_t* a2fxxx_bus)
+{
+ cyg_uint8 dma_tx_type, dma_rx_type;
+
+ if( a2fxxx_bus->setup->spi_reg_base == CYGHWR_HAL_A2FXXX_SPI1 ){
+ CYGHWR_HAL_A2FXXX_GPIO_SET( CYGHWR_HAL_A2FXXX_SPI1_DO );
+ CYGHWR_HAL_A2FXXX_GPIO_SET( CYGHWR_HAL_A2FXXX_SPI1_DI );
+ CYGHWR_HAL_A2FXXX_GPIO_SET( CYGHWR_HAL_A2FXXX_SPI1_CLK );
+ dma_tx_type = CYGHWR_HAL_A2FXXX_DMA_XFER(TO_SPI1);
+ dma_rx_type = CYGHWR_HAL_A2FXXX_DMA_XFER(FROM_SPI1);
+ }
+ else {
+ CYGHWR_HAL_A2FXXX_GPIO_SET( CYGHWR_HAL_A2FXXX_SPI0_DO );
+ CYGHWR_HAL_A2FXXX_GPIO_SET( CYGHWR_HAL_A2FXXX_SPI0_DI );
+ CYGHWR_HAL_A2FXXX_GPIO_SET( CYGHWR_HAL_A2FXXX_SPI0_CLK );
+ dma_tx_type = CYGHWR_HAL_A2FXXX_DMA_XFER(TO_SPI0);
+ dma_rx_type = CYGHWR_HAL_A2FXXX_DMA_XFER(FROM_SPI0);
+ }
+
+ // Initialize the synchronization primitives.
+ cyg_drv_mutex_init (&a2fxxx_bus->mutex);
+ cyg_drv_cond_init (&a2fxxx_bus->condvar, &a2fxxx_bus->mutex);
+
+ // Setup DMA channel
+ a2fxxx_dma_ch_setup(a2fxxx_bus->setup->dma_tx_channel, dma_tx_type,
+ CYGHWR_HAL_A2FXXX_DMA_OUTBOUND, sizeof(cyg_uint8), 0,
+ a2fxxx_bus->setup->dma_tx_pri, 9);
+ a2fxxx_dma_ch_setup(a2fxxx_bus->setup->dma_rx_channel, dma_rx_type,
+ CYGHWR_HAL_A2FXXX_DMA_INBOUND, 0, sizeof(cyg_uint8),
+ a2fxxx_bus->setup->dma_rx_pri, 9);
+
+ // Register ISR /DSR
+ a2fxxx_dma_ch_attach(a2fxxx_bus->setup->dma_tx_channel,
+ a2fxxx_tx_ISR, a2fxxx_tx_DSR, (cyg_addrword_t) a2fxxx_bus);
+
+ a2fxxx_dma_ch_attach(a2fxxx_bus->setup->dma_rx_channel,
+ a2fxxx_rx_ISR, a2fxxx_rx_DSR, (cyg_addrword_t) a2fxxx_bus);
+
+ // Call upper layer bus init.
+ CYG_SPI_BUS_COMMON_INIT(&a2fxxx_bus->spi_bus);
+}
+
+//-----------------------------------------------------------------------------
+// Drive a GPIO pin as a SPI chip select line.
+
+static inline void a2fxxx_spi_chip_select
+ (cyg_spi_device* device, cyg_bool assert)
+{
+ cyg_spi_cortexm_a2fxxx_device_t* a2fxxx_device =
+ (cyg_spi_cortexm_a2fxxx_device_t*) device;
+ cyg_spi_cortexm_a2fxxx_bus_t* a2fxxx_bus =
+ (cyg_spi_cortexm_a2fxxx_bus_t*) device->spi_bus;
+
+ // CS is driven from GPIO
+ if( a2fxxx_device->cs_gpio == true) {
+ if (assert == true)
+ CYGHWR_HAL_A2FXXX_GPIO_OUT( a2fxxx_device->cs_gpio_n, 0 );
+ else
+ CYGHWR_HAL_A2FXXX_GPIO_OUT( a2fxxx_device->cs_gpio_n, 1 );
+ }
+ // CS is driven from controller
+ else {
+ cyg_uint32 reg_addr = a2fxxx_bus->setup->spi_reg_base +
+ CYGHWR_HAL_A2FXXX_SPI_SLAVE_SEL;
+ cyg_uint32 reg_data;
+ HAL_READ_UINT32 (reg_addr, reg_data);
+ if (assert == true)
+ reg_data |= CYGHWR_HAL_A2FXXX_SPI_CS_SEL(a2fxxx_device->dev_num);
+ else
+ reg_data &= ~CYGHWR_HAL_A2FXXX_SPI_CS_SEL(a2fxxx_device->dev_num);
+ HAL_WRITE_UINT32 (reg_addr, reg_data);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Configure build-in SPI chip select line
+
+static inline void a2fxxx_spi_set_ss
+ (cyg_spi_cortexm_a2fxxx_bus_t* a2fxxx_bus, cyg_uint8 ss_num)
+{
+ cyg_uint32 ss;
+
+ if( a2fxxx_bus->setup->spi_reg_base == CYGHWR_HAL_A2FXXX_SPI0 ){
+ if ( ss_num == 0 ) {
+ ss = CYGHWR_HAL_A2FXXX_SPI0_SS0;
+ } else if( ss_num == 1 ) {
+ ss = CYGHWR_HAL_A2FXXX_SPI0_SS1;
+ } else if( ss_num == 2 ) {
+ ss = CYGHWR_HAL_A2FXXX_SPI0_SS2;
+ } else if( ss_num == 3 ) {
+ ss = CYGHWR_HAL_A2FXXX_SPI0_SS3;
+ } else {
+ CYG_ASSERT (ss < 4, "SPI : SPI0 SS out of range.");
+ return;
+ }
+ }
+ else {
+ if ( ss_num == 0 ) {
+ ss = CYGHWR_HAL_A2FXXX_SPI1_SS0;
+ } else if( ss_num == 1 ) {
+ ss = CYGHWR_HAL_A2FXXX_SPI1_SS1;
+ } else if( ss_num == 2 ) {
+ ss = CYGHWR_HAL_A2FXXX_SPI1_SS2;
+ } else if( ss_num == 3 ) {
+ ss = CYGHWR_HAL_A2FXXX_SPI1_SS3;
+ } else if( ss_num == 4 ) {
+ ss = CYGHWR_HAL_A2FXXX_SPI1_SS4;
+ } else if( ss_num == 5 ) {
+ ss = CYGHWR_HAL_A2FXXX_SPI1_SS5;
+ } else if( ss_num == 6 ) {
+ ss = CYGHWR_HAL_A2FXXX_SPI1_SS6;
+ } else if( ss_num == 7 ) {
+ ss = CYGHWR_HAL_A2FXXX_SPI1_SS7;
+ } else {
+ CYG_ASSERT (ss < 8, "SPI : SPI1 SS out of range.");
+ return;
+ }
+ }
+
+ CYGHWR_HAL_A2FXXX_GPIO_SET( ss );
+}
+
+//-----------------------------------------------------------------------------
+// Initiate a DMA transfer over the SPI interface.
+
+static void spi_transaction_dma
+ (cyg_spi_device* device, cyg_bool tick_only, cyg_bool polled, cyg_uint32 count,
+ const cyg_uint8* tx_data, cyg_uint8* rx_data, cyg_bool drop_cs)
+{
+ cyg_spi_cortexm_a2fxxx_bus_t* a2fxxx_bus =
+ (cyg_spi_cortexm_a2fxxx_bus_t*) device->spi_bus;
+ cyg_spi_cortexm_a2fxxx_device_t* a2fxxx_device =
+ (cyg_spi_cortexm_a2fxxx_device_t*) device;
+ cyg_haladdress reg_addr;
+ cyg_uint32 spi_cr_val = a2fxxx_device->spi_cr_val;
+ cyg_haladdress spi_reg_base = a2fxxx_bus->setup->spi_reg_base;
+
+ SPI_TRACE("SPI : Transfer start\n");
+
+ // Drive chip select low, either from GPIO or build in SS signal
+ if( !a2fxxx_bus->cs_up && !tick_only ){
+ SPI_TRACE("SPI : Setup CS\n");
+ CYGACC_CALL_IF_DELAY_US (a2fxxx_device->tr_bt_udly);
+ a2fxxx_spi_chip_select (device, true);
+ CYGACC_CALL_IF_DELAY_US (a2fxxx_device->cs_up_udly);
+ a2fxxx_bus->cs_up = true;
+ }
+
+ // Disable the SPI controller.
+ reg_addr = spi_reg_base + CYGHWR_HAL_A2FXXX_SPI_CTRL;
+ HAL_WRITE_UINT32 (reg_addr, a2fxxx_device->spi_cr_val);
+
+ // Write down transfer count
+ spi_cr_val |= CYGHWR_HAL_A2FXXX_SPI_CTRL_COUNT( count );
+ reg_addr = spi_reg_base + CYGHWR_HAL_A2FXXX_SPI_CTRL;
+ HAL_WRITE_UINT32 (reg_addr, spi_cr_val);
+
+ //
+ // Setup DMA channels
+ // For null source or destination pointer, replace the buffer with the SPI driver
+ // dummy buffer and set the DMA address increment to 0
+ //
+ if(tx_data == NULL)
+ a2fxxx_dma_update_incr(a2fxxx_bus->setup->dma_tx_channel, false, 0);
+ else
+ a2fxxx_dma_update_incr(a2fxxx_bus->setup->dma_tx_channel, false,
+ sizeof(cyg_uint8));
+
+ if(rx_data == NULL)
+ a2fxxx_dma_update_incr(a2fxxx_bus->setup->dma_rx_channel, true, 0);
+ else
+ a2fxxx_dma_update_incr(a2fxxx_bus->setup->dma_rx_channel, true,
+ sizeof(cyg_uint8));
+
+ a2fxxx_bus->tx_dma_done = false;
+ a2fxxx_dma_xfer (a2fxxx_bus->setup->dma_tx_channel, polled, count,
+ ((tx_data == NULL) ? (cyg_uint8*) a2fxxx_bus->setup->tx_dma_null :
+ (cyg_uint8*) tx_data),
+ (cyg_uint8*)(a2fxxx_bus->setup->spi_reg_base + CYGHWR_HAL_A2FXXX_SPI_TX));
+
+ a2fxxx_bus->rx_dma_done = false;
+ a2fxxx_dma_xfer (a2fxxx_bus->setup->dma_rx_channel, polled, count,
+ (cyg_uint8*)(a2fxxx_bus->setup->spi_reg_base + CYGHWR_HAL_A2FXXX_SPI_RX),
+ ((rx_data == NULL) ? (cyg_uint8*) a2fxxx_bus->setup->rx_dma_null :
+ (cyg_uint8*) rx_data));
+
+ //
+ // Run the DMA (polling for completion).
+ //
+ if (polled)
+ {
+ // Enable the SPI controller.
+ SPI_TRACE("SPI : Control Register 0x%x, 0x%x, %d\n", reg_addr,
+ spi_cr_val, count);
+ HAL_WRITE_UINT32 (reg_addr, spi_cr_val | CYGHWR_HAL_A2FXXX_SPI_CTRL_EN);
+
+ // Wait transfer completed.
+ do {
+ if(a2fxxx_dma_get_comp_flag(a2fxxx_bus->setup->dma_rx_channel))
+ a2fxxx_bus->rx_dma_done = true;
+ if(a2fxxx_dma_get_comp_flag(a2fxxx_bus->setup->dma_tx_channel))
+ a2fxxx_bus->tx_dma_done = true;
+ } while ( !(a2fxxx_bus->tx_dma_done && a2fxxx_bus->rx_dma_done) );
+
+ // Acknowledge transfer
+ a2fxxx_dma_clear_interrupt (a2fxxx_bus->setup->dma_rx_channel);
+ a2fxxx_dma_clear_interrupt (a2fxxx_bus->setup->dma_tx_channel);
+
+ } else {
+ cyg_drv_mutex_lock (&a2fxxx_bus->mutex);
+ cyg_drv_dsr_lock ();
+
+ // Enable the SPI controller.
+ SPI_TRACE("SPI : Control Register 0x%x, 0x%x, %d\n", reg_addr,
+ spi_cr_val, count);
+ HAL_WRITE_UINT32 (reg_addr, spi_cr_val | CYGHWR_HAL_A2FXXX_SPI_CTRL_EN);
+
+ // Sit back and wait for the ISR/DSRs to signal completion.
+ do {
+ cyg_drv_cond_wait (&a2fxxx_bus->condvar);
+ } while (!(a2fxxx_bus->tx_dma_done && a2fxxx_bus->rx_dma_done));
+
+ cyg_drv_dsr_unlock ();
+ cyg_drv_mutex_unlock (&a2fxxx_bus->mutex);
+ }
+
+ SPI_TRACE("SPI : Transfer completed\n");
+
+ if (drop_cs && !tick_only) {
+ SPI_TRACE("SPI : Release chip select\n");
+ CYGACC_CALL_IF_DELAY_US (a2fxxx_device->cs_dw_udly);
+ a2fxxx_spi_chip_select (device, false);
+ a2fxxx_bus->cs_up = false;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Initialize SPI interfaces on startup.
+
+static void CYGBLD_ATTRIB_C_INIT_PRI(CYG_INIT_BUS_SPI)
+a2fxxx_spi_init(void)
+{
+ hal_dma_init();
+
+#ifdef CYGHWR_DEVS_SPI_CORTEXM_A2FXXX_BUS1
+ CYGHWR_HAL_A2FXXX_PERIPH_RELEASE( CYGHWR_HAL_A2FXXX_PERIPH_SOFTRST(SPI0) );
+ a2fxxx_spi_bus_setup (&cyg_spi_a2fxxx_bus1);
+#endif
+
+#ifdef CYGHWR_DEVS_SPI_CORTEXM_A2FXXX_BUS2
+ CYGHWR_HAL_A2FXXX_PERIPH_RELEASE( CYGHWR_HAL_A2FXXX_PERIPH_SOFTRST(SPI1) );
+ a2fxxx_spi_bus_setup (&cyg_spi_a2fxxx_bus2);
+#endif
+}
+
+//-----------------------------------------------------------------------------
+// Start a SPI transaction.
+
+static void a2fxxx_transaction_begin
+ (cyg_spi_device* device)
+{
+ cyg_spi_cortexm_a2fxxx_bus_t* a2fxxx_bus =
+ (cyg_spi_cortexm_a2fxxx_bus_t*) device->spi_bus;
+ cyg_spi_cortexm_a2fxxx_device_t* a2fxxx_device =
+ (cyg_spi_cortexm_a2fxxx_device_t*) device;
+
+ cyg_haladdress reg_addr;
+ cyg_uint32 reg_data, divided_clk, br, cs_gpio_n;
+
+ SPI_TRACE("SPI : Transfer begin\n");
+ SPI_TRACE("SPI : Device baud rate = %d\n", a2fxxx_device->cl_brate);
+ SPI_TRACE("SPI : Device clock polarity = %d\n", a2fxxx_device->cl_pol);
+ SPI_TRACE("SPI : Device clock phase = %d\n", a2fxxx_device->cl_pha);
+
+ // On the first transaction, generate the values to be programmed into the
+ // SPI configuration registers for this device and cache them. This avoids
+ // having to recalculate the values for every transaction.
+ if (!a2fxxx_device->spi_cr_val) {
+
+ // SPI bus protocol
+ switch( a2fxxx_device->proto ) {
+ case A2FXXX_SPI_TI_SYNC_SERIAL:
+ reg_data = CYGHWR_HAL_A2FXXX_SPI_CTRL_PROTO_TI;
+ break;
+ case A2FXXX_SPI_NS_MICROWIRE:
+ reg_data = CYGHWR_HAL_A2FXXX_SPI_CTRL_PROTO_NS;
+ break;
+ default:
+ reg_data = CYGHWR_HAL_A2FXXX_SPI_CTRL_PROTO_MOTOROLA;
+ break;
+ }
+
+ // Bus polarity
+ if (a2fxxx_device->cl_pol)
+ reg_data |= CYGHWR_HAL_A2FXXX_SPI_CTRL_SPO;
+ if (a2fxxx_device->cl_pha)
+ reg_data |= CYGHWR_HAL_A2FXXX_SPI_CTRL_SPH;
+
+ // Master mode
+ reg_data |= CYGHWR_HAL_A2FXXX_SPI_CTRL_MASTER;
+
+ // Calculate the maximum viable bus speed.
+ divided_clk = hal_a2fxxx_spi_clock(a2fxxx_bus->setup->spi_reg_base) >> 1;
+ for (br = 0; (br < 7) && (divided_clk > a2fxxx_device->cl_brate); br++)
+ divided_clk >>= 1;
+
+ CYG_ASSERT (divided_clk <= a2fxxx_device->cl_brate,
+ "A2FXXX SPI : Cannot run bus slowly enough for peripheral.");
+
+ SPI_TRACE("SPI : Clock divider = %d\n", divided_clk);
+
+ reg_addr = a2fxxx_bus->setup->spi_reg_base +
+ CYGHWR_HAL_A2FXXX_SPI_CLK_GEN;
+ HAL_WRITE_UINT32 (reg_addr, br);
+
+ // Set transfer size (byte mode)
+ reg_addr = a2fxxx_bus->setup->spi_reg_base +
+ CYGHWR_HAL_A2FXXX_SPI_TXRXDF_SIZE;
+ HAL_WRITE_UINT32 (reg_addr, 8);
+
+ // Cache the configuration register settings.
+ a2fxxx_device->spi_cr_val = reg_data;
+
+ // Configure GPIO as chip select
+ if(a2fxxx_device->cs_gpio == true) {
+ cs_gpio_n = a2fxxx_device->cs_gpio_n;
+ SPI_TRACE("SPI : Setup GPIO for CS => %d\n", cs_gpio_n);
+ a2fxxx_device->cs_gpio_n =
+ CYGHWR_HAL_A2FXXX_CS_GPIO( cs_gpio_n, OUT, cs_gpio_n, DISABLE );
+ CYGHWR_HAL_A2FXXX_GPIO_SET( a2fxxx_device->cs_gpio_n );
+ CYGHWR_HAL_A2FXXX_GPIO_OUT( a2fxxx_device->cs_gpio_n, 1);
+ }
+ // Configure build-in SPI chip select line
+ else {
+ SPI_TRACE("SPI : Setup SPI SS => %d\n", a2fxxx_device->dev_num);
+ a2fxxx_spi_set_ss(a2fxxx_bus, a2fxxx_device->dev_num);
+ }
+ }
+
+ // Set up the SPI controller.
+ reg_addr = a2fxxx_bus->setup->spi_reg_base + CYGHWR_HAL_A2FXXX_SPI_CTRL;
+ HAL_WRITE_UINT32 (reg_addr, a2fxxx_device->spi_cr_val);
+}
+
+//-----------------------------------------------------------------------------
+// Run a transaction transfer.
+
+static void a2fxxx_transaction_transfer
+ (cyg_spi_device* device, cyg_bool polled, cyg_uint32 count,
+ const cyg_uint8* tx_data, cyg_uint8* rx_data, cyg_bool drop_cs)
+{
+ // Check for unsupported transactions.
+ CYG_ASSERT (count > 0, "A2FXXX SPI : Null transfer requested.");
+
+ // Perform transfer
+ spi_transaction_dma (device, false, polled, count, tx_data, rx_data, drop_cs);
+}
+
+//-----------------------------------------------------------------------------
+// Carry out a bus tick operation - this just pushes the required number of
+// zeros onto the bus, leaving the chip select in its current state.
+
+static void a2fxxx_transaction_tick
+ (cyg_spi_device* device, cyg_bool polled, cyg_uint32 count)
+{
+ // Check for unsupported transactions.
+ CYG_ASSERT (count > 0, "A2FXXX SPI : Null transfer requested.");
+
+ SPI_TRACE("SPI : Transfer tick\n");
+
+ // Perform null transfer.
+ spi_transaction_dma (device, true, polled, count, NULL, NULL, false);
+}
+
+//-----------------------------------------------------------------------------
+// Terminate a SPI transaction, disabling the SPI controller.
+
+static void a2fxxx_transaction_end
+ (cyg_spi_device* device)
+{
+ cyg_spi_cortexm_a2fxxx_bus_t* a2fxxx_bus =
+ (cyg_spi_cortexm_a2fxxx_bus_t*) device->spi_bus;
+ cyg_spi_cortexm_a2fxxx_device_t* a2fxxx_device =
+ (cyg_spi_cortexm_a2fxxx_device_t*) device;
+ cyg_haladdress reg_addr;
+
+ SPI_TRACE("SPI : Transfer end\n");
+
+ // De-assert chip select
+ if( a2fxxx_bus->cs_up == true ){
+ SPI_TRACE("SPI : Release chip select\n");
+ CYGACC_CALL_IF_DELAY_US (a2fxxx_device->cs_dw_udly);
+ a2fxxx_spi_chip_select (device, false);
+ a2fxxx_bus->cs_up = false;
+ }
+
+ // Disable controller
+ reg_addr = a2fxxx_bus->setup->spi_reg_base + CYGHWR_HAL_A2FXXX_SPI_CTRL;
+ HAL_WRITE_UINT32 (reg_addr, a2fxxx_device->spi_cr_val);
+}
+
+//-----------------------------------------------------------------------------
+// Note that no dynamic configuration options are currently defined.
+
+static int a2fxxx_get_config
+ (cyg_spi_device* dev, cyg_uint32 key, void* buf, cyg_uint32* len)
+{
+ return -1;
+}
+
+static int a2fxxx_set_config
+ (cyg_spi_device* dev, cyg_uint32 key, const void* buf, cyg_uint32* len)
+{
+ return -1;
+}
+
+#endif
+
+//=============================================================================
diff --git a/ecos/packages/devs/spi/cortexm/stm32/current/ChangeLog b/ecos/packages/devs/spi/cortexm/stm32/current/ChangeLog
new file mode 100644
index 0000000..ef60956
--- /dev/null
+++ b/ecos/packages/devs/spi/cortexm/stm32/current/ChangeLog
@@ -0,0 +1,140 @@
+2012-03-28 Jonathan Larmour <jifl@eCosCentric.com>
+
+ * src/spi_stm32.c (bus3_rx_bbuf): Fix typo in attribute.
+
+2012-03-23 James Smith <jsmith@ecoscentric.com>
+
+ * src/spi_stm32.c (CYGHWR_HAL_STM32_GPIO_MODE_OUT_SPEED_SPI):
+ Rename CYGHWR_HAL_STM32_GPIO_MODE_OUT_SPI to allow the same
+ SPEED_SPI value to be used for F1 and F2/F4 targets.
+ (SPI_CS): Use new wrapper macros to provide a single common SPI_CS
+ manifest.
+
+2012-03-15 James Smith <jsmith@ecoscentric.com>
+
+ * src/spi_stm32.c: Use HIPERFORMANCE manifest to allow F2 and F4
+ device GPIO initialisation support.
+ (dma_channel_setup): Avoid compiler pointer type warning.
+
+2012-03-05 James Smith <jsmith@ecoscentric.com>
+
+ * src/spi_stm32.c (spi_transaction_dma): Avoid race condition by
+ seting the TX and RX DMA done flags to false prior to configuring
+ (and starting) the DMA transfer.
+
+2012-01-12 Nick Garnett <nickg@ecoscentric.com>
+
+ * cdl/spi_stm32.cdl: Select pin toggle rate based on STM32
+ family. Define interrupt priorities to include DMA channel
+ priorities. Undo 2011-12-09 change, F2 now supported.
+
+ * include/spi_stm32.h (cyg_spi_cortexm_stm32_bus_s):
+ * src/spi_stm32.c: Substantial reorganization to use DMA API.
+ NOTE: Currently only fully tested on F2 parts.
+
+2011-12-09 Jonathan Larmour <jifl@eCosCentric.com>
+
+ * cdl/spi_stm32.cdl: For now, only allow this package to be
+ active with F1 family processors.
+
+2011-09-27 Ilija Stanislevik <ilijas@siva.mk>
+
+ * src/spi_stm32.c: Add support for CYG_IO_GET_CONFIG_SPI_CLOCKRATE and
+ CYG_IO_SET_CONFIG_SPI_CLOCKRATE (possibility to retrieve and to set
+ the SPI clockrate).
+
+2011-03-10 John Dallaway <john@dallaway.org.uk>
+
+ * cdl/spi_stm32.cdl: Add build options for CFLAGS and loopback test.
+
+2009-10-22 Nick Garnett <nickg@ecoscentric.com>
+
+ * cdl/spi_stm32.cdl: Fix descriptions for chip select
+ options. Only build local test if SPI bus 1 is active.
+
+ * include/spi_stm32.h (cyg_spi_cortexm_stm32_bus_setup_s): Add
+ spi_gpio_remap field.
+
+ * src/spi_stm32.c (bus1_setup, bus2_setup, bus3_setup): Fix CS
+ number calculation, add remap to each bus.
+ (stm32_spi_bus_setup): Move enables to correct place. Add code to
+ remap SPI pins if defined.
+
+2009-08-24 Simon Kallweit <simon.kallweit@intefo.ch>
+
+ * cdl/spi_stm32.cdl: added testcase.
+ * include/spi_stm32.h: initializing spi_cr1_val with zero.
+
+2009-06-29 Nick Garnett <nickg@ecoscentric.com>
+
+ * cdl/spi_stm32.cdl:
+ * include/spi_stm32.h (cyg_spi_cortexm_stm32_bus_setup_s):
+ * src/spi_stm32.c: Add support for individual device clock
+ enables. Also change mechanism for specifying CS lines that is
+ more in keeping with other devices.
+
+2009-03-23 Nick Garnett <nickg@ecoscentric.com>
+
+ * cdl/spi_stm32.cdl: Fix up a few oddities.
+
+ * src/spi_stm32.c (spi_diag): Add some diagnostics.
+
+2009-02-10 Bart Veer <bartv@ecoscentric.com>
+
+ * src/spi_stm32.c (cyg_spi_cortexm_stm32_init): mark as
+ prioritized constructor and rename.
+
+ * cdl/spi_stm32.cdl: stop building spi_stm32_init.cxx
+
+ * src/spi_stm32_init.cxx: removed, no longer needed.
+
+2009-02-10 Chris Holgate <chris@zynaptic.com>
+
+ * src/spi_stm32.c:
+ * cdl/spi_stm32.cdl:
+ Add option to automatically disable JTAG port when initialising SPI3.
+
+2009-02-10 Nick Garnett <nickg@ecoscentric.com>
+
+ * src/spi_stm32.c (bus3_setup): Fix typo.
+
+2009-02-05 Nick Garnett <nickg@ecoscentric.com>
+
+ * include/spi_stm32.h: Add macro to define an STM32 SPI device.
+
+ * src/spi_stm32.c: Fix potential compile error.
+
+ * src/spi_stm32_init.cxx: Change constructor init priority to use
+ CYG_INIT_BUS_SPI.
+
+2009-01-30 Nick Garnett <nickg@ecoscentric.com>
+
+ * cdl/spi_stm32.cdl:
+ * include/spi_stm32.h:
+ * src/spi_stm32.c:
+ * src/spi_stm32_init.cxx:
+ New package, STM32 SPI driver contributed by Chris Holgate.
+
+//===========================================================================
+// ####GPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 or (at your option) any
+// later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc., 51 Franklin Street,
+// Fifth Floor, Boston, MA 02110-1301, USA.
+// -------------------------------------------
+// ####GPLCOPYRIGHTEND####
+//===========================================================================
diff --git a/ecos/packages/devs/spi/cortexm/stm32/current/cdl/spi_stm32.cdl b/ecos/packages/devs/spi/cortexm/stm32/current/cdl/spi_stm32.cdl
new file mode 100644
index 0000000..32d5b24
--- /dev/null
+++ b/ecos/packages/devs/spi/cortexm/stm32/current/cdl/spi_stm32.cdl
@@ -0,0 +1,272 @@
+##=============================================================================
+##
+## spi_stm32.cdl
+##
+## STM32 SPI driver configuration options.
+##
+##=============================================================================
+## ####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating System.
+## Copyright (C) 2008, 2009, 2011, 2012 Free Software Foundation, Inc.
+##
+## eCos is free software; you can redistribute it and/or modify it under
+## the terms of the GNU General Public License as published by the Free
+## Software Foundation; either version 2 or (at your option) any later
+## version.
+##
+## eCos is distributed in the hope that it will be useful, but WITHOUT
+## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+## for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with eCos; if not, write to the Free Software Foundation, Inc.,
+## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+##
+## As a special exception, if other files instantiate templates or use
+## macros or inline functions from this file, or you compile this file
+## and link it with other works to produce a work based on this file,
+## this file does not by itself cause the resulting work to be covered by
+## the GNU General Public License. However the source code for this file
+## must still be made available in accordance with section (3) of the GNU
+## General Public License v2.
+##
+## This exception does not invalidate any other reasons why a work based
+## on this file might be covered by the GNU General Public License.
+## -------------------------------------------
+## ####ECOSGPLCOPYRIGHTEND####
+##=============================================================================
+#######DESCRIPTIONBEGIN####
+##
+## Author(s): Chris Holgate
+## Contributor: jld
+## Date: 2008-11-27
+## Purpose: Configure STM32 SPI driver.
+##
+######DESCRIPTIONEND####
+##
+##=============================================================================
+
+cdl_package CYGPKG_DEVS_SPI_CORTEXM_STM32 {
+ display "ST STM32 SPI driver"
+ description "
+ This package provides SPI driver support for the ST STM32 series
+ of microcontrollers.
+ "
+ parent CYGPKG_IO_SPI
+ active_if CYGPKG_IO_SPI
+ requires CYGPKG_HAL_CORTEXM_STM32
+ hardware
+ include_dir cyg/io
+ compile spi_stm32.c
+
+cdl_option CYGNUM_DEVS_SPI_CORTEXM_STM32_PIN_TOGGLE_RATE {
+ display "Pin toggle rate"
+ description "
+ Selects the pin toggle rate in MHz to be used for the SPI interfaces. Higher toggle
+ rates allow increased baud rates at the expense of power and EMI. Only certain rates
+ are valid on different STM32 families, check part documentation for which may be used."
+ flavor data
+ default_value { (CYGHWR_HAL_CORTEXM_STM32_FAMILY == "F1") ? 10 : 25 }
+ legal_values { 2 10 25 50 80 100 }
+}
+
+cdl_component CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS1 {
+ display "ST STM32 SPI bus 1"
+ description "
+ Enable SPI bus 1 on the STM32 device.
+ "
+ flavor bool
+ default_value 0
+
+ cdl_option CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS1_CS_GPIOS {
+ display "SPI chip selects"
+ description "
+ This is a comma separated list of GPIOs which are to be used as chip
+ select lines for the SPI bus. Each GPIO is defined by the SPI_CS()
+ macro which gives the port and pin number.
+ "
+ flavor data
+ default_value { "SPI_CS(A, 4)" }
+ }
+
+ cdl_option CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS1_BBUF_SIZE {
+ display "Bounce buffer size"
+ description "
+ DMA bounce buffers are required when running out of external
+ memory. Set this to the maximum SPI packet size which will be
+ used to enable the DMA bounce buffers. Set to 0 to disable
+ bounce buffers when running from on-chip memory.
+ "
+ flavor data
+ default_value 0
+ }
+
+ cdl_option CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS1_TXINTR_PRI {
+ display "Transmit DMA interrupt priority"
+ flavor data
+ default_value 64+5
+ }
+
+ cdl_option CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS1_RXINTR_PRI {
+ display "Receive DMA interrupt priority"
+ flavor data
+ default_value 128+6
+ }
+}
+
+cdl_component CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS2 {
+ display "ST STM32 SPI bus 2"
+ description "
+ Enable SPI bus 2 on the STM32 device.
+ "
+ flavor bool
+ default_value 0
+
+ cdl_option CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS2_CS_GPIOS {
+ display "SPI chip selects"
+ description "
+ This is a comma separated list of GPIOs which are to be used as chip
+ select lines for the SPI bus. Each GPIO is defined by the SPI_CS()
+ macro which gives the port and pin number.
+ "
+ flavor data
+ default_value { "SPI_CS(B, 12)" }
+ }
+
+ cdl_option CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS2_BBUF_SIZE {
+ display "Bounce buffer size"
+ description "
+ DMA bounce buffers are required when running out of external
+ memory. Set this to the maximum SPI packet size which will be
+ used to enable the DMA bounce buffers. Set to 0 to disable
+ bounce buffers when running from on-chip memory.
+ "
+ flavor data
+ default_value 0
+ }
+
+ cdl_option CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS2_TXINTR_PRI {
+ display "Transmit DMA interrupt priority"
+ flavor data
+ default_value 64+7
+ }
+
+ cdl_option CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS2_RXINTR_PRI {
+ display "Receive DMA interrupt priority"
+ flavor data
+ default_value 128+8
+ }
+}
+
+cdl_component CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS3 {
+ display "ST STM32 SPI bus 3"
+ description "
+ Enable SPI bus 3 on the STM32 device. Note that SPI bus 3 shares pins
+ with the JTAG port which means that debug should ideally be disabled
+ on startup. However, there is also the option of disabling it during
+ SPI bus initialisation instead.
+ "
+ flavor bool
+ default_value 0
+
+ cdl_option CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS3_DISABLE_DEBUG_PORT {
+ display "Disable debug port"
+ description "
+ When set the debug port will automatically be disabled on
+ initialising SPI bus 3, freeing up the SPI interface pins.
+ "
+ flavor bool
+ default_value 0
+ }
+
+ cdl_option CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS3_CS_GPIOS {
+ display "SPI chip selects"
+ description "
+ This is a comma separated list of GPIOs which are to be used as chip
+ select lines for the SPI bus. Each GPIO is defined by the SPI_CS()
+ macro which gives the port and pin number.
+ "
+ flavor data
+ default_value { "SPI_CS(A, 15)" }
+ }
+
+ cdl_option CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS3_BBUF_SIZE {
+ display "Bounce buffer size"
+ description "
+ DMA bounce buffers are required when running out of external
+ memory. Set this to the maximum SPI packet size which will be
+ used to enable the DMA bounce buffers. Set to 0 to disable
+ bounce buffers when running from on-chip memory.
+ "
+ flavor data
+ default_value 0
+ }
+
+ cdl_option CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS3_TXINTR_PRI {
+ display "Transmit DMA interrupt priority"
+ flavor data
+ default_value 64+9
+ }
+
+ cdl_option CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS3_RXINTR_PRI {
+ display "Receive DMA interrupt priority"
+ flavor data
+ default_value 128+10
+ }
+}
+
+cdl_component CYGPKG_DEVS_SPI_CORTEXM_STM32_OPTIONS {
+ display "ST STM32 SPI driver build options"
+ flavor none
+ description "
+ Package specific build options including control over
+ compiler flags used only in building this package,
+ and details of which tests are built."
+
+ cdl_option CYGPKG_DEVS_SPI_CORTEXM_STM32_CFLAGS_ADD {
+ display "Additional compiler flags"
+ flavor data
+ no_define
+ default_value { "" }
+ description "
+ This option modifies the set of compiler flags for
+ building the STM32 SPI driver. These flags are used in addition
+ to the set of global flags."
+ }
+
+ cdl_option CYGPKG_DEVS_SPI_CORTEXM_STM32_CFLAGS_REMOVE {
+ display "Suppressed compiler flags"
+ flavor data
+ no_define
+ default_value { "" }
+ description "
+ This option modifies the set of compiler flags for
+ building the STM32 SPI driver. These flags are removed from
+ the set of global flags if present."
+ }
+
+ cdl_option CYGBLD_DEVS_SPI_CORTEXM_STM32_LOOPBACK_TEST {
+ display "Build STM32 SPI loopback test"
+ flavor bool
+ no_define
+ default_value 0
+ requires CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS1
+ description "
+ This option enables the building of the STM32 SPI loopback test.
+ Refer to the comments in tests/loopback.c for details of how to
+ use this test."
+ }
+
+ cdl_option CYGPKG_DEVS_SPI_CORTEXM_STM32_TESTS {
+ display "SPI tests"
+ active_if CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS1
+ flavor data
+ no_define
+ calculated { CYGBLD_DEVS_SPI_CORTEXM_STM32_LOOPBACK_TEST ? "tests/loopback" : "" }
+ }
+}
+
+}
+# EOF spi_stm32.cdl
diff --git a/ecos/packages/devs/spi/cortexm/stm32/current/include/spi_stm32.h b/ecos/packages/devs/spi/cortexm/stm32/current/include/spi_stm32.h
new file mode 100644
index 0000000..a1370e2
--- /dev/null
+++ b/ecos/packages/devs/spi/cortexm/stm32/current/include/spi_stm32.h
@@ -0,0 +1,182 @@
+#ifndef CYGONCE_DEVS_SPI_CORTEXM_STM32_H
+#define CYGONCE_DEVS_SPI_CORTEXM_STM32_H
+//=============================================================================
+//
+// spi_stm32.h
+//
+// Header definitions for STM32 SPI driver.
+//
+//=============================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2008, 2009, 2012 Free Software Foundation, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later
+// version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with eCos; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// As a special exception, if other files instantiate templates or use
+// macros or inline functions from this file, or you compile this file
+// and link it with other works to produce a work based on this file,
+// this file does not by itself cause the resulting work to be covered by
+// the GNU General Public License. However the source code for this file
+// must still be made available in accordance with section (3) of the GNU
+// General Public License v2.
+//
+// This exception does not invalidate any other reasons why a work based
+// on this file might be covered by the GNU General Public License.
+// -------------------------------------------
+// ####ECOSGPLCOPYRIGHTEND####
+//=============================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Chris Holgate, nickg
+// Date: 2008-11-27
+// Purpose: STM32 SPI driver definitions.
+// Description:
+// Usage: #include <cyg/io/spi_stm32.h>
+//
+//####DESCRIPTIONEND####
+//
+//=============================================================================
+
+#include <pkgconf/hal.h>
+#include <pkgconf/io_spi.h>
+#include <pkgconf/devs_spi_cortexm_stm32.h>
+
+#include <cyg/infra/cyg_type.h>
+#include <cyg/hal/drv_api.h>
+#include <cyg/io/spi.h>
+
+#include <cyg/hal/var_dma.h>
+
+//-----------------------------------------------------------------------------
+// Macro for defining a SPI device and attaching it to the appropriate bus.
+//
+// _name_ is the name of the SPI device. This will be used to reference a
+// data structure of type cyg_spi_device which can be passed to the
+// SPI driver API without needing a cast.
+// _bus_ is the bus number to which this device is attached (1, 2 or 3).
+// _csnum_ is the chip select line used for this device, numbered from 0.
+// _16bit_ is set to true if the device uses 16 bit transactions and false
+// if the bus uses 8 bit transactions.
+// _clpol_ is the SPI bus clock polarity used by the device. This must be
+// set to 1 if a clock line pullup resistor is used and 0 if a
+// clock line pulldown resistor is used.
+// _clpha_ is the SPI bus clock phase used by the device.
+// _brate_ is the SPI bus clock baud rate used by the device, measured in Hz.
+// _csup_dly_ is the minimum delay between chip select assert and transfer
+// start, measured in microseconds.
+// _csdw_dly_ is the minimum delay between transfer end and chip select deassert,
+// measured in microseconds.
+// _trbt_dly_ is the minimum delay between consecutive transfers.
+
+#define CYG_DEVS_SPI_CORTEXM_STM32_DEVICE( \
+ _name_, _bus_, _csnum_, _16bit_, _clpol_, _clpha_, _brate_, _csup_dly_, _csdw_dly_, _trbt_dly_\
+) \
+cyg_spi_cortexm_stm32_device_t _name_ ##_stm32 CYG_SPI_DEVICE_ON_BUS(_bus_) = { \
+{ .spi_bus = (cyg_spi_bus*) &cyg_spi_stm32_bus## _bus_ }, \
+ .dev_num = _csnum_, \
+ .bus_16bit = _16bit_ ? 1 : 0, \
+ .cl_pol = _clpol_, \
+ .cl_pha = _clpha_, \
+ .cl_brate = _brate_, \
+ .cs_up_udly = _csup_dly_, \
+ .cs_dw_udly = _csdw_dly_, \
+ .tr_bt_udly = _trbt_dly_, \
+ .spi_cr1_val = 0, \
+}; \
+extern cyg_spi_device _name_ __attribute__((alias ( #_name_ "_stm32" )));
+
+//-----------------------------------------------------------------------------
+// STM32 SPI bus configuration and state.
+
+typedef struct cyg_spi_cortexm_stm32_bus_setup_s
+{
+ cyg_uint32 *apb_freq; // Peripheral bus frequency.
+ cyg_haladdress spi_reg_base; // Base address of SPI register block.
+
+ cyg_uint32 spi_enable; // SPI bus clock enable
+ cyg_uint8 cs_gpio_num; // Number of chip selects for this bus.
+ const cyg_uint32* cs_gpio_list; // List of GPIOs used as chip selects.
+ const cyg_uint32* spi_gpio_list; // List of GPIOs used by the SPI interface.
+ cyg_uint32 spi_gpio_remap; // Remap GPIO lines to alternate pins.
+ cyg_priority_t dma_tx_intr_pri; // Interrupt priority for DMA transmit.
+ cyg_priority_t dma_rx_intr_pri; // Interrupt priority for DMA receive.
+ cyg_uint32 bbuf_size; // Size of bounce buffers.
+ cyg_uint8* bbuf_tx; // Pointer to transmit bounce buffer.
+ cyg_uint8* bbuf_rx; // Pointer to receive bounce buffer.
+
+} cyg_spi_cortexm_stm32_bus_setup_t;
+
+typedef struct cyg_spi_cortexm_stm32_bus_s
+{
+ // ---- Upper layer data ----
+ cyg_spi_bus spi_bus; // Upper layer SPI bus data.
+
+ // ---- Bus configuration constants ----
+ const cyg_spi_cortexm_stm32_bus_setup_t* setup;
+
+ // ---- Driver state (private) ----
+
+ hal_stm32_dma_stream dma_tx_stream; // TX DMA stream for this bus.
+ hal_stm32_dma_stream dma_rx_stream; // RX DMA stream for this bus.
+ cyg_drv_mutex_t mutex; // Transfer mutex.
+ cyg_drv_cond_t condvar; // Transfer condition variable.
+ cyg_bool tx_dma_done; // Flags used to signal completion.
+ cyg_bool rx_dma_done; // Flags used to signal completion.
+ cyg_bool cs_up; // Chip select asserted flag.
+
+} cyg_spi_cortexm_stm32_bus_t;
+
+//-----------------------------------------------------------------------------
+// STM32 SPI device.
+
+typedef struct cyg_spi_cortexm_stm32_device_s
+{
+ // ---- Upper layer data ----
+ cyg_spi_device spi_device; // Upper layer SPI device data.
+
+ // ---- Device setup (user configurable) ----
+ cyg_uint8 dev_num; // Device number.
+ cyg_uint8 bus_16bit; // Use 16 bit (1) or 8 bit (0) transfers.
+ cyg_uint8 cl_pol; // Clock polarity (0 or 1).
+ cyg_uint8 cl_pha; // Clock phase (0 or 1).
+ cyg_uint32 cl_brate; // Clock baud rate.
+ cyg_uint16 cs_up_udly; // Minimum delay in us between CS up and transfer start.
+ cyg_uint16 cs_dw_udly; // Minimum delay in us between transfer end and CS down.
+ cyg_uint16 tr_bt_udly; // Minimum delay in us between two transfers.
+
+ // ---- Device state (private) ----
+ cyg_uint32 spi_cr1_val; // SPI configuration register (initialised to 0).
+
+} cyg_spi_cortexm_stm32_device_t;
+
+//-----------------------------------------------------------------------------
+// Exported bus data structures.
+
+#ifdef CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS1
+externC cyg_spi_cortexm_stm32_bus_t cyg_spi_stm32_bus1;
+#endif
+
+#ifdef CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS2
+externC cyg_spi_cortexm_stm32_bus_t cyg_spi_stm32_bus2;
+#endif
+
+#ifdef CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS3
+externC cyg_spi_cortexm_stm32_bus_t cyg_spi_stm32_bus3;
+#endif
+
+//=============================================================================
+#endif // CYGONCE_DEVS_SPI_CORTEXM_STM32_H
diff --git a/ecos/packages/devs/spi/cortexm/stm32/current/src/spi_stm32.c b/ecos/packages/devs/spi/cortexm/stm32/current/src/spi_stm32.c
new file mode 100644
index 0000000..54a97b1
--- /dev/null
+++ b/ecos/packages/devs/spi/cortexm/stm32/current/src/spi_stm32.c
@@ -0,0 +1,805 @@
+//=============================================================================
+//
+// spi_stm32.c
+//
+// SPI driver implementation for STM32
+//
+//=============================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2008, 2009, 2011, 2012 Free Software Foundation, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later
+// version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with eCos; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// As a special exception, if other files instantiate templates or use
+// macros or inline functions from this file, or you compile this file
+// and link it with other works to produce a work based on this file,
+// this file does not by itself cause the resulting work to be covered by
+// the GNU General Public License. However the source code for this file
+// must still be made available in accordance with section (3) of the GNU
+// General Public License v2.
+//
+// This exception does not invalidate any other reasons why a work based
+// on this file might be covered by the GNU General Public License.
+// -------------------------------------------
+// ####ECOSGPLCOPYRIGHTEND####
+//=============================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Chris Holgate, nickg
+// Date: 2008-11-27
+// Purpose: STM32 SPI driver implementation
+//
+//####DESCRIPTIONEND####
+//
+//=============================================================================
+
+#include <cyg/hal/hal_io.h>
+#include <cyg/hal/hal_if.h>
+#include <cyg/hal/hal_intr.h>
+#include <cyg/hal/drv_api.h>
+
+#include <cyg/infra/cyg_type.h>
+#include <cyg/infra/cyg_ass.h>
+#include <cyg/infra/diag.h>
+
+#include <cyg/io/spi.h>
+#include <cyg/io/spi_stm32.h>
+
+#include <pkgconf/devs_spi_cortexm_stm32.h>
+
+#include <string.h>
+
+//-----------------------------------------------------------------------------
+// Diagnostics
+
+#if 0
+#define spi_diag( __fmt, ... ) diag_printf("SPI: %30s[%3d]: " __fmt, __FUNCTION__, __LINE__, ## __VA_ARGS__ );
+#define spi_dump_buf( __addr, __size ) diag_dump_buf( __addr, __size )
+#else
+#define spi_diag( __fmt, ... )
+#define spi_dump_buf( __addr, __size )
+#endif
+
+//-----------------------------------------------------------------------------
+// Bus frequencies
+
+__externC cyg_uint32 hal_stm32_pclk1;
+__externC cyg_uint32 hal_stm32_pclk2;
+
+//-----------------------------------------------------------------------------
+// API function call forward references.
+
+static void stm32_transaction_begin (cyg_spi_device*);
+static void stm32_transaction_transfer (cyg_spi_device*, cyg_bool, cyg_uint32, const cyg_uint8*, cyg_uint8*, cyg_bool);
+static void stm32_transaction_tick (cyg_spi_device*, cyg_bool, cyg_uint32);
+static void stm32_transaction_end (cyg_spi_device*);
+static int stm32_get_config (cyg_spi_device*, cyg_uint32, void*, cyg_uint32*);
+static int stm32_set_config (cyg_spi_device*, cyg_uint32, const void*, cyg_uint32*);
+
+//-----------------------------------------------------------------------------
+// DMA callbacks
+
+static void stm32_dma_tx_callback( hal_stm32_dma_stream *stream, cyg_uint32 count, CYG_ADDRWORD data );
+static void stm32_dma_rx_callback( hal_stm32_dma_stream *stream, cyg_uint32 count, CYG_ADDRWORD data );
+
+//-----------------------------------------------------------------------------
+// Null data source and sink must be placed in the on-chip SRAM. This is
+// either done explicitly (bounce buffers instantiated) or implicitly (no
+// bounce buffers implies that the data area is already on SRAM).
+
+#if (defined (CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS1) && (CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS1_BBUF_SIZE > 0)) || \
+ (defined (CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS2) && (CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS2_BBUF_SIZE > 0)) || \
+ (defined (CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS3) && (CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS3_BBUF_SIZE > 0))
+static cyg_uint16 dma_tx_null __attribute__((section (".sram"))) = 0xFFFF;
+static cyg_uint16 dma_rx_null __attribute__((section (".sram"))) = 0xFFFF;
+
+#else
+static cyg_uint16 dma_tx_null = 0xFFFF;
+static cyg_uint16 dma_rx_null = 0xFFFF;
+#endif
+
+//-----------------------------------------------------------------------------
+// Useful GPIO macros for 'dynamic' pin setup.
+
+#if defined (CYGHWR_HAL_CORTEXM_STM32_FAMILY_F1)
+
+#if (CYGNUM_DEVS_SPI_CORTEXM_STM32_PIN_TOGGLE_RATE == 2)
+#define CYGHWR_HAL_STM32_GPIO_MODE_OUT_SPEED_SPI CYGHWR_HAL_STM32_GPIO_MODE_OUT_2MHZ
+
+#elif (CYGNUM_DEVS_SPI_CORTEXM_STM32_PIN_TOGGLE_RATE == 10)
+#define CYGHWR_HAL_STM32_GPIO_MODE_OUT_SPEED_SPI CYGHWR_HAL_STM32_GPIO_MODE_OUT_10MHZ
+
+#elif (CYGNUM_DEVS_SPI_CORTEXM_STM32_PIN_TOGGLE_RATE == 50)
+#define CYGHWR_HAL_STM32_GPIO_MODE_OUT_SPEED_SPI CYGHWR_HAL_STM32_GPIO_MODE_OUT_50MHZ
+
+#else
+#error "Invalid SPI bus toggle rate."
+#endif
+
+#elif defined (CYGHWR_HAL_CORTEXM_STM32_FAMILY_HIPERFORMANCE)
+
+#if (CYGNUM_DEVS_SPI_CORTEXM_STM32_PIN_TOGGLE_RATE == 2)
+#define CYGHWR_HAL_STM32_GPIO_OSPEED_SPEED_SPI CYGHWR_HAL_STM32_GPIO_OSPEED_2MHZ
+
+#elif (CYGNUM_DEVS_SPI_CORTEXM_STM32_PIN_TOGGLE_RATE == 25)
+#define CYGHWR_HAL_STM32_GPIO_OSPEED_SPEED_SPI CYGHWR_HAL_STM32_GPIO_OSPEED_25MHZ
+
+#elif (CYGNUM_DEVS_SPI_CORTEXM_STM32_PIN_TOGGLE_RATE == 50)
+#define CYGHWR_HAL_STM32_GPIO_OSPEED_SPEED_SPI CYGHWR_HAL_STM32_GPIO_OSPEED_50MHZ
+
+#elif (CYGNUM_DEVS_SPI_CORTEXM_STM32_PIN_TOGGLE_RATE == 80)
+#define CYGHWR_HAL_STM32_GPIO_OSPEED_SPEED_SPI CYGHWR_HAL_STM32_GPIO_OSPEED_HIGH
+
+#elif (CYGNUM_DEVS_SPI_CORTEXM_STM32_PIN_TOGGLE_RATE == 100)
+#define CYGHWR_HAL_STM32_GPIO_OSPEED_SPEED_SPI CYGHWR_HAL_STM32_GPIO_OSPEED_HIGH
+
+#else
+#error "Invalid SPI bus toggle rate."
+#endif
+
+#else
+
+#error "Unknown STM32 family"
+
+#endif
+
+#define SPI_CS( __port, __bit ) CYGHWR_HAL_STM32_PIN_OUT( __port, __bit, PUSHPULL, NONE, SPEED_SPI )
+
+//-----------------------------------------------------------------------------
+
+// Instantiate the bus state data structures.
+
+#ifdef CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS1
+static const cyg_uint32 bus1_cs_gpio_list[] = { CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS1_CS_GPIOS };
+static const cyg_uint32 bus1_spi_gpio_list[] = { CYGHWR_HAL_STM32_SPI1_SCK,
+ CYGHWR_HAL_STM32_SPI1_MISO,
+ CYGHWR_HAL_STM32_SPI1_MOSI };
+
+#if (CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS1_BBUF_SIZE > 0)
+static cyg_uint8 bus1_tx_bbuf [CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS1_BBUF_SIZE]
+ __attribute__((aligned (2), section (".sram"))) = { 0 };
+static cyg_uint8 bus1_rx_bbuf [CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS1_BBUF_SIZE]
+ __attribute__((aligned (2), section (".sram"))) = { 0 };
+#endif
+
+static const cyg_spi_cortexm_stm32_bus_setup_t bus1_setup = {
+ .apb_freq = &hal_stm32_pclk2,
+ .spi_reg_base = CYGHWR_HAL_STM32_SPI1,
+ .spi_enable = CYGHWR_HAL_STM32_SPI1_CLOCK,
+ .cs_gpio_num = sizeof (bus1_cs_gpio_list)/sizeof(cyg_uint32),
+ .cs_gpio_list = bus1_cs_gpio_list,
+ .spi_gpio_list = bus1_spi_gpio_list,
+ .spi_gpio_remap = CYGHWR_HAL_STM32_SPI1_REMAP_CONFIG,
+ .dma_tx_intr_pri = CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS1_TXINTR_PRI,
+ .dma_rx_intr_pri = CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS1_RXINTR_PRI,
+
+#if (CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS1_BBUF_SIZE > 0)
+ .bbuf_size = CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS1_BBUF_SIZE,
+ .bbuf_tx = bus1_tx_bbuf,
+ .bbuf_rx = bus1_rx_bbuf,
+#else
+ .bbuf_size = 0,
+#endif
+};
+
+cyg_spi_cortexm_stm32_bus_t cyg_spi_stm32_bus1 = {
+ .spi_bus.spi_transaction_begin = stm32_transaction_begin,
+ .spi_bus.spi_transaction_transfer = stm32_transaction_transfer,
+ .spi_bus.spi_transaction_tick = stm32_transaction_tick,
+ .spi_bus.spi_transaction_end = stm32_transaction_end,
+ .spi_bus.spi_get_config = stm32_get_config,
+ .spi_bus.spi_set_config = stm32_set_config,
+ .setup = &bus1_setup,
+ .cs_up = false,
+
+ .dma_tx_stream.desc = CYGHWR_HAL_STM32_SPI1_DMA_TX,
+ .dma_tx_stream.callback = stm32_dma_tx_callback,
+ .dma_tx_stream.data = (CYG_ADDRWORD)&cyg_spi_stm32_bus1,
+
+ .dma_rx_stream.desc = CYGHWR_HAL_STM32_SPI1_DMA_RX,
+ .dma_rx_stream.callback = stm32_dma_rx_callback,
+ .dma_rx_stream.data = (CYG_ADDRWORD)&cyg_spi_stm32_bus1,
+
+
+
+};
+#endif
+
+#ifdef CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS2
+static const cyg_uint32 bus2_cs_gpio_list[] = { CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS2_CS_GPIOS };
+static const cyg_uint32 bus2_spi_gpio_list[] = { CYGHWR_HAL_STM32_SPI2_SCK,
+ CYGHWR_HAL_STM32_SPI2_MISO,
+ CYGHWR_HAL_STM32_SPI2_MOSI };
+
+#if (CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS2_BBUF_SIZE > 0)
+static cyg_uint8 bus2_tx_bbuf [CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS2_BBUF_SIZE]
+ __attribute__((aligned (2), section (".sram"))) = { 0 };
+static cyg_uint8 bus2_rx_bbuf [CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS2_BBUF_SIZE]
+ __attribute__((aligned (2), section (".sram"))) = { 0 };
+#endif
+
+static const cyg_spi_cortexm_stm32_bus_setup_t bus2_setup = {
+ .apb_freq = &hal_stm32_pclk1,
+ .spi_reg_base = CYGHWR_HAL_STM32_SPI2,
+ .spi_enable = CYGHWR_HAL_STM32_SPI2_CLOCK,
+ .cs_gpio_num = sizeof (bus2_cs_gpio_list)/sizeof(cyg_uint32),
+ .cs_gpio_list = bus2_cs_gpio_list,
+ .spi_gpio_list = bus2_spi_gpio_list,
+ .spi_gpio_remap = CYGHWR_HAL_STM32_SPI2_REMAP_CONFIG,
+ .dma_tx_intr_pri = CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS2_TXINTR_PRI,
+ .dma_rx_intr_pri = CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS2_RXINTR_PRI,
+
+#if (CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS2_BBUF_SIZE > 0)
+ .bbuf_size = CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS2_BBUF_SIZE,
+ .bbuf_tx = bus2_tx_bbuf,
+ .bbuf_rx = bus2_rx_bbuf,
+#else
+ .bbuf_size = 0,
+#endif
+};
+
+cyg_spi_cortexm_stm32_bus_t cyg_spi_stm32_bus2 = {
+ .spi_bus.spi_transaction_begin = stm32_transaction_begin,
+ .spi_bus.spi_transaction_transfer = stm32_transaction_transfer,
+ .spi_bus.spi_transaction_tick = stm32_transaction_tick,
+ .spi_bus.spi_transaction_end = stm32_transaction_end,
+ .spi_bus.spi_get_config = stm32_get_config,
+ .spi_bus.spi_set_config = stm32_set_config,
+ .setup = &bus2_setup,
+ .cs_up = false,
+
+ .dma_tx_stream.desc = CYGHWR_HAL_STM32_SPI2_DMA_TX,
+ .dma_tx_stream.callback = stm32_dma_tx_callback,
+ .dma_tx_stream.data = (CYG_ADDRWORD)&cyg_spi_stm32_bus2,
+
+ .dma_rx_stream.desc = CYGHWR_HAL_STM32_SPI2_DMA_RX,
+ .dma_rx_stream.callback = stm32_dma_rx_callback,
+ .dma_rx_stream.data = (CYG_ADDRWORD)&cyg_spi_stm32_bus2,
+
+
+};
+#endif
+
+#ifdef CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS3
+static const cyg_uint32 bus3_cs_gpio_list[] = { CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS3_CS_GPIOS };
+static const cyg_uint32 bus3_spi_gpio_list[] = { CYGHWR_HAL_STM32_SPI3_SCK,
+ CYGHWR_HAL_STM32_SPI3_MISO,
+ CYGHWR_HAL_STM32_SPI3_MOSI };
+
+#if (CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS3_BBUF_SIZE > 0)
+static cyg_uint8 bus3_tx_bbuf [CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS3_BBUF_SIZE]
+ __attribute__((aligned (2), section (".sram"))) = { 0 };
+static cyg_uint8 bus3_rx_bbuf [CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS3_BBUF_SIZE]
+ __attribute__((aligned (2), section (".sram"))) = { 0 };
+#endif
+
+static const cyg_spi_cortexm_stm32_bus_setup_t bus3_setup = {
+ .apb_freq = &hal_stm32_pclk1,
+ .spi_reg_base = CYGHWR_HAL_STM32_SPI3,
+ .spi_enable = CYGHWR_HAL_STM32_SPI3_CLOCK,
+ .cs_gpio_num = sizeof (bus3_cs_gpio_list)/sizeof(cyg_uint32),
+ .cs_gpio_list = bus3_cs_gpio_list,
+ .spi_gpio_list = bus3_spi_gpio_list,
+ .spi_gpio_remap = CYGHWR_HAL_STM32_SPI3_REMAP_CONFIG,
+ .dma_tx_intr_pri = CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS3_TXINTR_PRI,
+ .dma_rx_intr_pri = CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS3_RXINTR_PRI,
+
+#if (CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS3_BBUF_SIZE > 0)
+ .bbuf_size = CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS3_BBUF_SIZE,
+ .bbuf_tx = bus3_tx_bbuf,
+ .bbuf_rx = bus3_rx_bbuf,
+#else
+ .bbuf_size = 0,
+#endif
+};
+
+cyg_spi_cortexm_stm32_bus_t cyg_spi_stm32_bus3 = {
+ .spi_bus.spi_transaction_begin = stm32_transaction_begin,
+ .spi_bus.spi_transaction_transfer = stm32_transaction_transfer,
+ .spi_bus.spi_transaction_tick = stm32_transaction_tick,
+ .spi_bus.spi_transaction_end = stm32_transaction_end,
+ .spi_bus.spi_get_config = stm32_get_config,
+ .spi_bus.spi_set_config = stm32_set_config,
+ .setup = &bus3_setup,
+ .cs_up = false,
+
+ .dma_tx_stream.desc = CYGHWR_HAL_STM32_SPI3_DMA_TX,
+ .dma_tx_stream.callback = stm32_dma_tx_callback,
+ .dma_tx_stream.data = (CYG_ADDRWORD)&cyg_spi_stm32_bus3,
+
+ .dma_rx_stream.desc = CYGHWR_HAL_STM32_SPI3_DMA_RX,
+ .dma_rx_stream.callback = stm32_dma_rx_callback,
+ .dma_rx_stream.data = (CYG_ADDRWORD)&cyg_spi_stm32_bus3,
+
+
+};
+#endif
+
+//-----------------------------------------------------------------------------
+// Configure a GPIO pin as a SPI chip select line.
+
+static inline void stm32_spi_gpio_cs_setup
+ (cyg_uint32 gpio_num)
+{
+ CYGHWR_HAL_STM32_GPIO_SET (gpio_num);
+ CYGHWR_HAL_STM32_GPIO_OUT (gpio_num, 1);
+}
+
+//-----------------------------------------------------------------------------
+// Drive a GPIO pin as a SPI chip select line.
+
+static inline void stm32_spi_chip_select
+ (cyg_uint32 gpio_num, cyg_bool assert)
+{
+ CYGHWR_HAL_STM32_GPIO_OUT( gpio_num, assert ? 0 : 1);
+}
+
+//-----------------------------------------------------------------------------
+// DMA Callbacks. The DMA driver has disabled the DMA channel and
+// masked the interrupt condition, here we need to wake up the client
+// thread.
+
+static void stm32_dma_tx_callback( hal_stm32_dma_stream *stream, cyg_uint32 count, CYG_ADDRWORD data )
+{
+ cyg_spi_cortexm_stm32_bus_t* stm32_bus = (cyg_spi_cortexm_stm32_bus_t*) data;
+
+ cyg_drv_dsr_lock ();
+ stm32_bus->tx_dma_done = true;
+ cyg_drv_cond_signal (&stm32_bus->condvar);
+ cyg_drv_dsr_unlock ();
+}
+
+static void stm32_dma_rx_callback( hal_stm32_dma_stream *stream, cyg_uint32 count, CYG_ADDRWORD data )
+{
+ cyg_spi_cortexm_stm32_bus_t* stm32_bus = (cyg_spi_cortexm_stm32_bus_t*) data;
+
+ cyg_drv_dsr_lock ();
+ stm32_bus->rx_dma_done = true;
+ cyg_drv_cond_signal (&stm32_bus->condvar);
+ cyg_drv_dsr_unlock ();
+}
+
+//-----------------------------------------------------------------------------
+// Set up a new SPI bus on initialisation.
+
+static void stm32_spi_bus_setup
+ (cyg_spi_cortexm_stm32_bus_t* stm32_bus)
+{
+ int i;
+ cyg_haladdress reg_addr;
+ cyg_uint32 reg_data;
+
+ spi_diag("bus %p\n", stm32_bus );
+ // Set up the GPIOs for use as chip select lines.
+ for (i = 0; i < stm32_bus->setup->cs_gpio_num; i ++) {
+ stm32_spi_gpio_cs_setup (stm32_bus->setup->cs_gpio_list[i]);
+ }
+
+#if defined (CYGHWR_HAL_CORTEXM_STM32_FAMILY_F1)
+ // Remap GPIO pins if required
+ if( stm32_bus->setup->spi_gpio_remap )
+ {
+ CYG_ADDRESS afio = CYGHWR_HAL_STM32_AFIO;
+ cyg_uint32 mapr;
+ spi_diag("remap %08x\n", stm32_bus->setup->spi_gpio_remap );
+ CYGHWR_HAL_STM32_CLOCK_ENABLE( CYGHWR_HAL_STM32_AFIO_CLOCK );
+ HAL_READ_UINT32( afio+CYGHWR_HAL_STM32_AFIO_MAPR, mapr );
+ mapr |= stm32_bus->setup->spi_gpio_remap;
+ HAL_WRITE_UINT32( afio+CYGHWR_HAL_STM32_AFIO_MAPR, mapr );
+ }
+#endif
+
+ CYGHWR_HAL_STM32_GPIO_SET( stm32_bus->setup->spi_gpio_list[0] );
+ CYGHWR_HAL_STM32_GPIO_SET( stm32_bus->setup->spi_gpio_list[1] );
+ CYGHWR_HAL_STM32_GPIO_SET( stm32_bus->setup->spi_gpio_list[2] );
+
+ CYGHWR_HAL_STM32_CLOCK_ENABLE( stm32_bus->setup->spi_enable );
+ //CYGHWR_HAL_STM32_CLOCK_ENABLE( stm32_bus->setup->dma_enable );
+
+ // Set up SPI default configuration.
+ reg_addr = stm32_bus->setup->spi_reg_base + CYGHWR_HAL_STM32_SPI_CR2;
+ reg_data = CYGHWR_HAL_STM32_SPI_CR2_TXDMAEN | CYGHWR_HAL_STM32_SPI_CR2_RXDMAEN;
+ HAL_WRITE_UINT32 (reg_addr, reg_data);
+
+ // Initialise the synchronisation primitivies.
+ cyg_drv_mutex_init (&stm32_bus->mutex);
+ cyg_drv_cond_init (&stm32_bus->condvar, &stm32_bus->mutex);
+
+ // Initialize DMA streams
+ hal_stm32_dma_init( &stm32_bus->dma_tx_stream, stm32_bus->setup->dma_tx_intr_pri );
+ hal_stm32_dma_init( &stm32_bus->dma_rx_stream, stm32_bus->setup->dma_rx_intr_pri );
+
+ // Call upper layer bus init.
+ CYG_SPI_BUS_COMMON_INIT(&stm32_bus->spi_bus);
+}
+
+//-----------------------------------------------------------------------------
+// Set up a DMA channel.
+
+static void dma_channel_setup
+ (cyg_spi_device* device, cyg_uint8* data_buf, cyg_uint32 count, cyg_bool is_tx, cyg_bool polled)
+{
+ cyg_spi_cortexm_stm32_bus_t* stm32_bus = (cyg_spi_cortexm_stm32_bus_t*) device->spi_bus;
+ cyg_spi_cortexm_stm32_device_t* stm32_device = (cyg_spi_cortexm_stm32_device_t*) device;
+ hal_stm32_dma_stream *stream = is_tx ? &stm32_bus->dma_tx_stream : &stm32_bus->dma_rx_stream;
+
+ hal_stm32_dma_configure( stream,
+ stm32_device->bus_16bit ? 16 : 8,
+ (data_buf==NULL),
+ polled );
+
+ if( data_buf == NULL )
+ data_buf = (cyg_uint8 *)(is_tx ? &dma_tx_null : &dma_rx_null);
+
+ hal_stm32_dma_start( stream,
+ data_buf,
+ stm32_bus->setup->spi_reg_base+CYGHWR_HAL_STM32_SPI_DR,
+ count );
+
+ hal_stm32_dma_show( stream );
+}
+
+//-----------------------------------------------------------------------------
+// Initiate a DMA transfer over the SPI interface.
+
+static void spi_transaction_dma
+ (cyg_spi_device* device, cyg_bool tick_only, cyg_bool polled, cyg_uint32 count,
+ const cyg_uint8* tx_data, cyg_uint8* rx_data, cyg_bool drop_cs)
+{
+ cyg_spi_cortexm_stm32_bus_t* stm32_bus = (cyg_spi_cortexm_stm32_bus_t*) device->spi_bus;
+ cyg_spi_cortexm_stm32_device_t* stm32_device = (cyg_spi_cortexm_stm32_device_t*) device;
+
+ cyg_haladdress reg_addr;
+
+ cyg_haladdress spi_reg_base = stm32_bus->setup->spi_reg_base;
+
+ spi_diag("device %p\n", device );
+ // Ensure the chip select is asserted, inserting inter-transaction guard
+ // time if required. Note that when ticking the device we do not touch the CS.
+ if (!stm32_bus->cs_up && !tick_only) {
+ CYGACC_CALL_IF_DELAY_US (stm32_device->tr_bt_udly);
+ stm32_spi_chip_select (stm32_bus->setup->cs_gpio_list[stm32_device->dev_num], true);
+ stm32_bus->cs_up = true;
+ CYGACC_CALL_IF_DELAY_US (stm32_device->cs_up_udly);
+ }
+
+ // Clear done flags prior to configuring DMA:
+ stm32_bus->tx_dma_done = false;
+ stm32_bus->rx_dma_done = false;
+
+ // Set up the DMA channels.
+ dma_channel_setup (device, (cyg_uint8*) tx_data, count, true, polled);
+ dma_channel_setup (device, rx_data, count, false, polled);
+
+ // Run the DMA (polling for completion).
+ if (polled) {
+ // Enable the SPI controller.
+ reg_addr = spi_reg_base + CYGHWR_HAL_STM32_SPI_CR1;
+ HAL_WRITE_UINT32 (reg_addr, stm32_device->spi_cr1_val | CYGHWR_HAL_STM32_SPI_CR1_SPE);
+
+ while( !(stm32_bus->tx_dma_done && stm32_bus->rx_dma_done) )
+ {
+ hal_stm32_dma_poll( &stm32_bus->dma_tx_stream );
+ hal_stm32_dma_poll( &stm32_bus->dma_rx_stream );
+ }
+ }
+ // Run the DMA (interrupt driven).
+ else {
+ cyg_drv_mutex_lock (&stm32_bus->mutex);
+ cyg_drv_dsr_lock ();
+
+ // Enable the SPI controller.
+ reg_addr = spi_reg_base + CYGHWR_HAL_STM32_SPI_CR1;
+ HAL_WRITE_UINT32 (reg_addr, stm32_device->spi_cr1_val | CYGHWR_HAL_STM32_SPI_CR1_SPE);
+
+ // Sit back and wait for the ISR/DSRs to signal completion.
+ do {
+ cyg_drv_cond_wait (&stm32_bus->condvar);
+ } while (!(stm32_bus->tx_dma_done && stm32_bus->rx_dma_done));
+
+ cyg_drv_dsr_unlock ();
+ cyg_drv_mutex_unlock (&stm32_bus->mutex);
+ }
+
+
+ // Disable the SPI controller.
+ reg_addr = spi_reg_base + CYGHWR_HAL_STM32_SPI_CR1;
+ HAL_WRITE_UINT32 (reg_addr, stm32_device->spi_cr1_val);
+
+ // Deassert the chip select.
+ if (drop_cs && !tick_only) {
+ CYGACC_CALL_IF_DELAY_US (stm32_device->cs_dw_udly);
+ stm32_spi_chip_select (stm32_bus->setup->cs_gpio_list[stm32_device->dev_num], false);
+ stm32_bus->cs_up = false;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Calculate BR bits for SPI_CR1.
+static int calculate_br_bits
+ (cyg_spi_cortexm_stm32_bus_t* bus, cyg_uint32 *target_clockrate, cyg_uint32 *br)
+{
+ cyg_uint32 divided_clk;
+
+ // Calculate the maximum viable bus speed.
+ divided_clk = *bus->setup->apb_freq / 2;
+ for (*br = 0; (*br < 7) && (divided_clk > *target_clockrate); (*br)++)
+ divided_clk >>= 1;
+
+ if ( divided_clk <= *target_clockrate )
+ return 0;
+
+ return -1;
+}
+
+//-----------------------------------------------------------------------------
+// Initialise SPI interfaces on startup.
+
+static void CYGBLD_ATTRIB_C_INIT_PRI(CYG_INIT_BUS_SPI)
+stm32_spi_init(void)
+{
+ spi_diag("\n");
+#if defined(CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS3) && \
+ defined(CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS3_DISABLE_DEBUG_PORT)
+ // Disable debug port, freeing up SPI bus 3 pins.
+ cyg_uint32 reg_val;
+ HAL_READ_UINT32 (CYGHWR_HAL_STM32_AFIO + CYGHWR_HAL_STM32_AFIO_MAPR, reg_val);
+ reg_val &= ~((cyg_uint32) CYGHWR_HAL_STM32_AFIO_MAPR_SWJ_MASK);
+ reg_val |= CYGHWR_HAL_STM32_AFIO_MAPR_SWJ_SWDPDIS;
+ HAL_WRITE_UINT32 (CYGHWR_HAL_STM32_AFIO + CYGHWR_HAL_STM32_AFIO_MAPR, reg_val);
+#endif
+
+#ifdef CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS1
+ stm32_spi_bus_setup (&cyg_spi_stm32_bus1);
+#endif
+
+#ifdef CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS2
+ stm32_spi_bus_setup (&cyg_spi_stm32_bus2);
+#endif
+
+#ifdef CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS3
+ stm32_spi_bus_setup (&cyg_spi_stm32_bus3);
+#endif
+}
+
+//-----------------------------------------------------------------------------
+// Start a SPI transaction.
+
+static void stm32_transaction_begin
+ (cyg_spi_device* device)
+{
+ cyg_spi_cortexm_stm32_bus_t* stm32_bus = (cyg_spi_cortexm_stm32_bus_t*) device->spi_bus;
+ cyg_spi_cortexm_stm32_device_t* stm32_device = (cyg_spi_cortexm_stm32_device_t*) device;
+
+ cyg_haladdress reg_addr;
+ cyg_uint32 reg_data, br;
+
+ spi_diag("\n");
+ // On the first transaction, generate the values to be programmed into the
+ // SPI configuration registers for this device and cache them. This avoids
+ // having to recalculate the prescaler for every transaction.
+ if (!stm32_device->spi_cr1_val) {
+ reg_data = CYGHWR_HAL_STM32_SPI_CR1_MSTR |
+ CYGHWR_HAL_STM32_SPI_CR1_SSI | CYGHWR_HAL_STM32_SPI_CR1_SSM;
+ if (stm32_device->cl_pol)
+ reg_data |= CYGHWR_HAL_STM32_SPI_CR1_CPOL;
+ if (stm32_device->cl_pha)
+ reg_data |= CYGHWR_HAL_STM32_SPI_CR1_CPHA;
+ if (stm32_device->bus_16bit)
+ reg_data |= CYGHWR_HAL_STM32_SPI_CR1_DFF;
+
+ // Get divider bits
+ if ( 0 != calculate_br_bits(stm32_bus, (cyg_uint32 *)&(stm32_device->cl_brate), &br) )
+ CYG_ASSERT (false, "STM32 SPI : Cannot run bus slowly enough for peripheral.");
+
+ reg_data |= CYGHWR_HAL_STM32_SPI_CR1_BR (br);
+
+ // Cache the configuration register settings.
+ stm32_device->spi_cr1_val = reg_data;
+ }
+
+ // Set up the SPI controller.
+ reg_addr = stm32_bus->setup->spi_reg_base + CYGHWR_HAL_STM32_SPI_CR1;
+ HAL_WRITE_UINT32 (reg_addr, stm32_device->spi_cr1_val);
+}
+
+//-----------------------------------------------------------------------------
+// Run a transaction transfer.
+
+static void stm32_transaction_transfer
+ (cyg_spi_device* device, cyg_bool polled, cyg_uint32 count,
+ const cyg_uint8* tx_data, cyg_uint8* rx_data, cyg_bool drop_cs)
+{
+ cyg_spi_cortexm_stm32_bus_t* stm32_bus = (cyg_spi_cortexm_stm32_bus_t*) device->spi_bus;
+ cyg_spi_cortexm_stm32_device_t* stm32_device = (cyg_spi_cortexm_stm32_device_t*) device;
+
+ // Check for unsupported transactions.
+ CYG_ASSERT (count > 0, "STM32 SPI : Null transfer requested.");
+
+ spi_diag("count %d\n", count);
+ if( tx_data ) spi_dump_buf(tx_data, count );
+
+ // We check that the buffers are half-word aligned and that count is a
+ // multiple of two in order to carry out the 16-bit transfer.
+ if (stm32_device->bus_16bit) {
+ CYG_ASSERT (!(count & 1) && !((cyg_uint32) tx_data & 1) && !((cyg_uint32) rx_data & 1),
+ "STM32 SPI : Misaligned data in 16-bit transfer.");
+ }
+
+ // Perform transfer via the bounce buffers.
+ if (stm32_bus->setup->bbuf_size != 0) {
+ cyg_uint8* tx_local = NULL;
+ cyg_uint8* rx_local = NULL;
+
+ // If the requested transfer is too large for the bounce buffer we assert
+ // in debug builds and truncate in production builds.
+ if (count > stm32_bus->setup->bbuf_size) {
+ CYG_ASSERT (false, "STM32 SPI : Transfer exceeds bounce buffer size.");
+ count = stm32_bus->setup->bbuf_size;
+ }
+ if (tx_data != NULL) {
+ tx_local = stm32_bus->setup->bbuf_tx;
+ memcpy (tx_local, tx_data, count);
+ }
+ if (rx_data != NULL) {
+ rx_local = stm32_bus->setup->bbuf_rx;
+ }
+ spi_transaction_dma (device, false, polled, count, tx_local, rx_local, drop_cs);
+ if (rx_data != NULL) {
+ memcpy (rx_data, rx_local, count);
+ }
+ }
+
+ // Perform conventional transfer.
+ else {
+ spi_transaction_dma (device, false, polled, count, tx_data, rx_data, drop_cs);
+ }
+
+ spi_diag("done\n");
+ if( rx_data ) spi_dump_buf(rx_data, count );
+
+}
+
+//-----------------------------------------------------------------------------
+// Carry out a bus tick operation - this just pushes the required number of
+// zeros onto the bus, leaving the chip select in its current state.
+
+static void stm32_transaction_tick
+ (cyg_spi_device* device, cyg_bool polled, cyg_uint32 count)
+{
+ cyg_spi_cortexm_stm32_device_t* stm32_device = (cyg_spi_cortexm_stm32_device_t*) device;
+
+ // Check for unsupported transactions.
+ CYG_ASSERT (count > 0, "STM32 SPI : Null transfer requested.");
+
+ spi_diag("count %d\n", count);
+
+ // We check that count is a multiple of two in order to carry out the 16-bit transfer.
+ if (stm32_device->bus_16bit) {
+ CYG_ASSERT (!(count & 1),
+ "STM32 SPI : Misaligned data in 16-bit transfer.");
+ }
+
+ // Perform null transfer.
+ spi_transaction_dma (device, true, polled, count, NULL, NULL, false);
+}
+
+//-----------------------------------------------------------------------------
+// Terminate a SPI transaction, disabling the SPI controller.
+
+static void stm32_transaction_end
+ (cyg_spi_device* device)
+{
+ cyg_spi_cortexm_stm32_bus_t* stm32_bus = (cyg_spi_cortexm_stm32_bus_t*) device->spi_bus;
+ cyg_spi_cortexm_stm32_device_t* stm32_device = (cyg_spi_cortexm_stm32_device_t*) device;
+
+ cyg_haladdress reg_addr;
+
+ spi_diag("\n");
+ // Ensure that the chip select is deasserted.
+ if (stm32_bus->cs_up) {
+ CYGACC_CALL_IF_DELAY_US (stm32_device->cs_dw_udly);
+ stm32_spi_chip_select (stm32_bus->setup->cs_gpio_list[stm32_device->dev_num], false);
+ stm32_bus->cs_up = false;
+ }
+
+ // Ensure the SPI controller is disabled.
+ reg_addr = stm32_bus->setup->spi_reg_base + CYGHWR_HAL_STM32_SPI_CR1;
+ HAL_WRITE_UINT32 (reg_addr, stm32_device->spi_cr1_val);
+}
+
+//-----------------------------------------------------------------------------
+static int stm32_get_config
+ (cyg_spi_device* device, cyg_uint32 key, void* buf, cyg_uint32* len)
+{
+ cyg_spi_cortexm_stm32_bus_t* stm32_bus = (cyg_spi_cortexm_stm32_bus_t*) device->spi_bus;
+ cyg_spi_cortexm_stm32_device_t* stm32_device = (cyg_spi_cortexm_stm32_device_t*) device;
+ cyg_uint32* data_p = buf;
+
+ switch (key)
+ {
+ case CYG_IO_GET_CONFIG_SPI_CLOCKRATE :
+ // Sanity check
+ if (NULL == len) {
+ CYG_ASSERT (false, "STM32 SPI : Null pointer as len argument for stm32_get_config().");
+ return -1;
+ }
+ if (sizeof(cyg_uint32) != *len) {
+ CYG_ASSERT (false, "STM32 SPI : Invalid length with stm32_get_config().");
+ return -1;
+ }
+ if (NULL == buf) {
+ CYG_ASSERT (false, "STM32 SPI : Null poiter as buf argument for stm32_get_config().");
+ return -1;
+ }
+
+ *data_p = *stm32_bus->setup->apb_freq >> ((( stm32_device->spi_cr1_val >> 3 ) & 7) + 1 ) ;
+ return 0;
+
+ default :
+ break;
+ }
+
+ return -1;
+}
+
+//-----------------------------------------------------------------------------
+static int stm32_set_config
+ (cyg_spi_device* device, cyg_uint32 key, const void* buf, cyg_uint32* len)
+{
+ cyg_spi_cortexm_stm32_bus_t* stm32_bus = (cyg_spi_cortexm_stm32_bus_t*) device->spi_bus;
+ cyg_spi_cortexm_stm32_device_t* stm32_device = (cyg_spi_cortexm_stm32_device_t*) device;
+
+ cyg_uint32 br;
+
+ switch (key)
+ {
+ case CYG_IO_SET_CONFIG_SPI_CLOCKRATE :
+ // Sanity check
+ if (NULL == len) {
+ CYG_ASSERT (false, "STM32 SPI : Null pointer as len argument for stm32_set_config().");
+ return -1;
+ }
+ if (sizeof(cyg_uint32) != *len) {
+ CYG_ASSERT (false, "STM32 SPI : Invalid length with stm32_set_config().");
+ return -1;
+ }
+ if (NULL == buf) {
+ CYG_ASSERT (false, "STM32 SPI : Null pointer as buf argument for stm32_set_config().");
+ return -1;
+ }
+
+ // Get divider bits
+ if ( 0 != calculate_br_bits(stm32_bus, (cyg_uint32 *)buf, &br) ) {
+ CYG_ASSERT (false, "STM32 SPI : Cannot run bus as slowly as requested.");
+ return -1;
+ }
+
+ // Update the cache of the configuration register settings.
+ stm32_device->spi_cr1_val &= ~CYGHWR_HAL_STM32_SPI_CR1_BR(7);
+ stm32_device->spi_cr1_val |= CYGHWR_HAL_STM32_SPI_CR1_BR(br);
+
+ return 0;
+
+ default :
+ break;
+ }
+
+ return -1;
+}
+
+//=============================================================================
diff --git a/ecos/packages/devs/spi/cortexm/stm32/current/tests/loopback.c b/ecos/packages/devs/spi/cortexm/stm32/current/tests/loopback.c
new file mode 100644
index 0000000..876ab45
--- /dev/null
+++ b/ecos/packages/devs/spi/cortexm/stm32/current/tests/loopback.c
@@ -0,0 +1,185 @@
+//=============================================================================
+//
+// loopback.c
+//
+// Standalone SPI loopback test.
+//
+//=============================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later
+// version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with eCos; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// As a special exception, if other files instantiate templates or use
+// macros or inline functions from this file, or you compile this file
+// and link it with other works to produce a work based on this file,
+// this file does not by itself cause the resulting work to be covered by
+// the GNU General Public License. However the source code for this file
+// must still be made available in accordance with section (3) of the GNU
+// General Public License v2.
+//
+// This exception does not invalidate any other reasons why a work based
+// on this file might be covered by the GNU General Public License.
+// -------------------------------------------
+// ####ECOSGPLCOPYRIGHTEND####
+//=============================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Chris Holgate
+// Date: 2008-11-27
+// Purpose: STM32 SPI loopback test
+// Description: Standalone SPI loopback test.
+// Usage: Compile as a standalone application.
+//
+//####DESCRIPTIONEND####
+//
+//=============================================================================
+
+//=============================================================================
+// This is a quick loopback test for the STM32 SPI driver. It only checks
+// the data transfer functionality - chip select handling will require
+// testing with external devices. In order to run the test, the MOSI and
+// MISO pins for the test port need to be shorted together to provide an
+// external loopback. Don't do this on a bus which has external devices
+// attached unless you first make sure that none of them are connected to
+// the chip select used by the test harness.
+// The default port and chip select used for this test are SPI bus 1,
+// chip select 0. These can be changed by editing the loopback_device
+// data structure directly.
+// Note that this is intended to be run as a standalone test and not as part
+// of the standard board tests since it requires a hardware modification.
+//=============================================================================
+
+#include <cyg/infra/cyg_type.h>
+#include <cyg/infra/testcase.h> // Test macros
+#include <cyg/infra/cyg_ass.h> // Assertion macros
+#include <cyg/infra/diag.h> // Diagnostic output
+
+#include <cyg/hal/hal_arch.h> // CYGNUM_HAL_STACK_SIZE_TYPICAL
+#include <cyg/kernel/kapi.h>
+
+#include <cyg/io/spi.h> // Common SPI API
+#include <cyg/io/spi_stm32.h> // STM32 data structures
+
+#include <string.h>
+
+//---------------------------------------------------------------------------
+// Thread data structures.
+
+cyg_uint8 stack [CYGNUM_HAL_STACK_SIZE_TYPICAL];
+cyg_thread thread_data;
+cyg_handle_t thread_handle;
+
+externC cyg_spi_cortexm_stm32_bus_t cyg_spi_stm32_bus2;
+
+//---------------------------------------------------------------------------
+// SPI loopback device driver data structures.
+
+cyg_spi_cortexm_stm32_device_t loopback_device = {
+ .spi_device.spi_bus = &cyg_spi_stm32_bus1.spi_bus,
+ .dev_num = 0 , // Only 1 device.
+ .cl_pol = 1,
+ .cl_pha = 1,
+ .cl_brate = 8000000, // Nominal 8Mhz.
+ .cs_up_udly = 1,
+ .cs_dw_udly = 1,
+ .tr_bt_udly = 1,
+ .bus_16bit = false,
+};
+
+//---------------------------------------------------------------------------
+
+const char tx_data[] = "Testing, testing, 12, 123.";
+const char tx_data1[] = "Testing extended API...";
+const char tx_data2[] = "Testing extended API for a second transaction.";
+
+char rx_data [sizeof(tx_data)];
+char rx_data1 [sizeof(tx_data1)];
+char rx_data2 [sizeof(tx_data2)];
+
+//---------------------------------------------------------------------------
+// Run single loopback transaction using simple transfer API call.
+
+void run_test_1 (cyg_bool polled)
+{
+ diag_printf ("Test 1 : Simple transfer test (polled = %d).\n", polled ? 1 : 0);
+ cyg_spi_transfer (&loopback_device.spi_device, polled, sizeof (tx_data),
+ (const cyg_uint8*) &tx_data[0], (cyg_uint8*) &rx_data[0]);
+
+ diag_printf (" Tx data : %s\n", tx_data);
+ diag_printf (" Rx data : %s\n", rx_data);
+ CYG_ASSERT (memcmp (tx_data, rx_data, sizeof (tx_data)) == 0,
+ "Simple transfer loopback failed - mismatched data.\n");
+}
+
+//---------------------------------------------------------------------------
+// Run two loopback transactions using extended transfer API.
+
+void run_test_2 (cyg_bool polled)
+{
+ diag_printf ("Test 2 : Extended API test (polled = %d).\n", polled ? 1 : 0);
+ cyg_spi_transaction_begin (&loopback_device.spi_device);
+ cyg_spi_transaction_transfer (&loopback_device.spi_device, polled, sizeof (tx_data1),
+ (const cyg_uint8*) &tx_data1[0], (cyg_uint8*) &rx_data1[0], false);
+ cyg_spi_transaction_transfer (&loopback_device.spi_device, polled, sizeof (tx_data2),
+ (const cyg_uint8*) &tx_data2[0], (cyg_uint8*) &rx_data2[0], false);
+ cyg_spi_transaction_end (&loopback_device.spi_device);
+
+ diag_printf (" Tx data 1 : %s\n", tx_data1);
+ diag_printf (" Rx data 1 : %s\n", rx_data1);
+ diag_printf (" Tx data 2 : %s\n", tx_data2);
+ diag_printf (" Rx data 2 : %s\n", rx_data2);
+ CYG_ASSERT (memcmp (tx_data1, rx_data1, sizeof (tx_data1)) == 0,
+ "Simple transfer loopback failed - mismatched data (transfer 1).\n");
+ CYG_ASSERT (memcmp (tx_data2, rx_data2, sizeof (tx_data2)) == 0,
+ "Simple transfer loopback failed - mismatched data (transfer 2).\n");
+}
+
+//---------------------------------------------------------------------------
+// Run all PL022 SPI interface loopback tests.
+
+void run_tests (void)
+{
+ diag_printf ("Running STM32 SPI driver loopback tests.\n");
+ run_test_1 (true);
+ run_test_1 (false);
+ run_test_2 (true);
+ run_test_2 (false);
+ CYG_TEST_PASS_FINISH ("Loopback tests ran OK");
+}
+
+//---------------------------------------------------------------------------
+// User startup - tests are run in their own thread.
+
+void cyg_user_start(void)
+{
+ CYG_TEST_INIT();
+ cyg_thread_create(
+ 10, // Arbitrary priority
+ (cyg_thread_entry_t*) run_tests, // Thread entry point
+ 0, //
+ "test_thread", // Thread name
+ &stack[0], // Stack
+ CYGNUM_HAL_STACK_SIZE_TYPICAL, // Stack size
+ &thread_handle, // Thread handle
+ &thread_data // Thread data structure
+ );
+ cyg_thread_resume(thread_handle);
+ cyg_scheduler_start();
+}
+
+//=============================================================================
diff --git a/ecos/packages/devs/spi/freescale/dspi/current/ChangeLog b/ecos/packages/devs/spi/freescale/dspi/current/ChangeLog
new file mode 100644
index 0000000..ca08fc7
--- /dev/null
+++ b/ecos/packages/devs/spi/freescale/dspi/current/ChangeLog
@@ -0,0 +1,79 @@
+2013-07-09 Mike Jones <mjones@proclivis.com>
+
+ * src/spi_freescale_dspi.c: Fix: Kinetis DSPI infinite polling
+ [ Bugzilla 10011879 ]
+
+2013-05-08 Ilija Kocho <ilijak@siva.com.mk>
+
+ * src/spi_freescale_dspi.cdl: Add CYGINT_DEVS_SPI_DMA_USE
+ * src/spi_freescale_dspi.c: Fix: Disable DMA requests for transfers
+ that don't use DMA. [ Bugzilla 1001815 ]
+
+2013-04-01 Ilija Kocho <ilijak@siva.com.mk>
+
+ * include/spi_freescale_dspi.h, include/spi_freescale_busses.inl
+ * include/spi_freescale_dspi_io.h, src/spi_freescale_dspi.c:
+ Optimised receiving of messages that fit in FIFO. Add clock gating.
+ Fix race condition bug in dspi_transaction_end(). [ Bugzilla 1001815 ]
+
+2013-02-06 Stefan Singer <stefan.singer@freescale.com>
+ Ilija Kocho <ilijak@siva.com.mk>
+
+ * include/spi_freescale_dspi.h, include/spi_freescale_busses.inl
+ * include/spi_freescale_dspi_io.h, include/spi_freescale_dspi_bd.h,
+ * src/spi_freescale_dspi.c:
+ enhanced endianness support for devices with big and little endian
+ added support for MPC5xxx in addition to Kinetis
+ extended support for up to 8 DSPIs
+ (see Bugzilla 1001752).
+
+2012-12-28 Ilija Kocho <ilijak@siva.com.mk>
+
+ * cdl/spi_freescale_dspi.cdl, src/spi_freescale_dspi.c:
+ Tick-only now has option to beehive like other drivers
+ rather than RM (see Bugzilla 1001676).
+ Fixed bug with dropping CS. Chip select options consolidated in a for loop.
+
+ * tests/spi_loopback.c: New file. Add looback test.
+ [Bugzilla 1001719]
+
+2012-05-04 Ilija Kocho <ilijak@siva.com.mk>
+
+ * cdl/spi_freescale_dspi.cdl:
+ * include/spi_freescale_dspi_buses.inl
+ * src/spi_freescale_dspi.c:
+ Add: support for 32 channel eDMA, support for cached memory.
+ [Bugzilla 1001579]
+
+2012-01-06 Ilija Kocho <ilijak@siva.com.mk>
+
+ * cdl/spi_freescale_dspi.cdl:
+ * include/spi_freescale_dspi.h
+ * include/spi_freescale_dspi_io.h:
+ * include/spi_freescale_dspi_buses.inl
+ * src/spi_freescale_dspi.c:
+ New package -- Freescale DSPI SPI driver. [Bugzilla 1001450]
+
+//===========================================================================
+// ####GPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2012 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 or (at your option) any
+// later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc., 51 Franklin Street,
+// Fifth Floor, Boston, MA 02110-1301, USA.
+// -------------------------------------------
+// ####GPLCOPYRIGHTEND####
+//===========================================================================
diff --git a/ecos/packages/devs/spi/freescale/dspi/current/cdl/spi_freescale_dspi.cdl b/ecos/packages/devs/spi/freescale/dspi/current/cdl/spi_freescale_dspi.cdl
new file mode 100644
index 0000000..f1be8ba
--- /dev/null
+++ b/ecos/packages/devs/spi/freescale/dspi/current/cdl/spi_freescale_dspi.cdl
@@ -0,0 +1,387 @@
+##=============================================================================
+##
+## spi_freescale_dspi.cdl
+##
+## Freescale DSPI driver configuration options.
+##
+##=============================================================================
+## ####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating System.
+## Copyright (C) 2011 Free Software Foundation, Inc.
+##
+## eCos is free software; you can redistribute it and/or modify it under
+## the terms of the GNU General Public License as published by the Free
+## Software Foundation; either version 2 or (at your option) any later
+## version.
+##
+## eCos is distributed in the hope that it will be useful, but WITHOUT
+## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+## for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with eCos; if not, write to the Free Software Foundation, Inc.,
+## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+##
+## As a special exception, if other files instantiate templates or use
+## macros or inline functions from this file, or you compile this file
+## and link it with other works to produce a work based on this file,
+## this file does not by itself cause the resulting work to be covered by
+## the GNU General Public License. However the source code for this file
+## must still be made available in accordance with section (3) of the GNU
+## General Public License v2.
+##
+## This exception does not invalidate any other reasons why a work based
+## on this file might be covered by the GNU General Public License.
+## -------------------------------------------
+## ####ECOSGPLCOPYRIGHTEND####
+##=============================================================================
+#######DESCRIPTIONBEGIN####
+##
+## Author(s): Ilija Kocho
+## Date: 2011-11-03
+## Purpose: Configure Freescale DSPI driver.
+##
+######DESCRIPTIONEND####
+##
+##=============================================================================
+
+cdl_package CYGPKG_DEVS_SPI_FREESCALE_DSPI {
+ display "Freescale DSPI driver"
+ description "
+ This package provides SPI driver support for the Freescale
+ microcontrollers that employ DSPI interface."
+
+ parent CYGPKG_IO_SPI
+ active_if CYGPKG_IO_SPI
+ requires CYGPKG_HAL_CORTEXM_KINETIS || CYGPKG_HAL_POWERPC_MPC5xxx
+
+ hardware
+ include_dir cyg/io
+ compile spi_freescale_dspi.c
+
+ cdl_option CYGHWR_DEVS_SPI_FREESCALE_DSPI_FIFO_SIZE {
+ display "DSPI FIFO size"
+ flavor data
+ default_value 4
+ legal_values { 4 5 6 7 8 }
+ }
+
+ cdl_component CYGHWR_DEVS_SPI_FREESCALE_DSPI_CTAR_NUM {
+ display "CTAR registers"
+ flavor data
+ calculated 2
+
+ description "DSPI can have from 2 to 8 CTAR registers that keep
+ transfer communication settings. In eCos CTAR0 is used for
+ all normal transfers while CTAR1 is used as auxiliary for
+ 'transaction end' (non)transfer."
+
+ cdl_component CYGHWR_DEVS_SPI_FREESCALEDSPI_DSPI_CTAR1_AUX {
+ display "CTAR1 Aux settings"
+ flavor none
+ no_define
+
+ cdl_component CYGHWR_DEVS_FREESCALEDSPI_DSPI_CTAR1_AUX_SPEED {
+ display "Nominal clock speed Hz"
+ flavor data
+ default_value 25000000
+
+ cdl_option CYGHWR_DEVS_FREESCALEDSPI_DSPI_CTAR1_AUX_USE_DBR {
+ display "Use double baud rate"
+ flavor bool
+ default_value 1
+ description "Double baud rate is a feature of Freescale DSPI
+ that may provide higher baud rates but duty the cycle may be
+ different than 50/50 depdent on scaler/prescaler setting
+ for achieved baud rate."
+ }
+ }
+
+ cdl_option CYGHWR_DEVS_FREESCALEDSPI_DSPI_CTAR1_AUX_CS_DELAY {
+ display "Nominal chip select delay (units)"
+ flavor data
+ legal_values { 1 to 1000 }
+ default_value 1
+ }
+
+ cdl_option CYGHWR_DEVS_FREESCALE_DSPI_DSPI_CTAR1_AUX_DELAY_UNIT {
+ display "Chip select delay unit (ns)"
+ flavor data
+ calculated 100
+ }
+ }
+ }
+
+ cdl_interface CYGINT_DEVS_SPI_DSPI_DMA_USE {
+ display "DSPI DMA use"
+ flavor data
+ description "Number of DMA channels used by DSPI buses."
+ }
+
+ for { set ::spibus 0 } { $::spibus < 8 } { incr ::spibus } {
+
+ cdl_interface CYGINT_DEVS_SPI_FREESCALE_DSPI[set ::spibus] {
+ display "Number of devices using DSPI bus [set ::spibus]"
+ }
+
+ cdl_component CYGHWR_DEVS_SPI_FREESCALE_DSPI[set ::spibus] {
+ display "Freescale DSPI bus [set ::spibus]"
+ description "Enable DSPI bus [set :: spibus]."
+ flavor bool
+ default_value CYGINT_DEVS_SPI_FREESCALE_DSPI[set ::spibus]
+ active_if CYGINT_DEVS_SPI_FREESCALE_DSPI[set ::spibus]
+
+ implements CYGINT_HAL_DMA
+ requires CYGPKG_HAL_FREESCALE_EDMA
+
+ cdl_component CYGHWR_DEVS_SPI_FREESCALE_DSPI[set ::spibus]_CS {
+ display "Chip-selects"
+ flavor none
+ no_define
+ cdl_option CYHGWR_DEVS_SPI_FREESCALE_DSPI[set ::spibus]_PCSS {
+ display "Chip-select Strobe enable"
+ flavor bool
+ default_value 0
+
+ requires CYHGWR_DEVS_SPI_FREESCALE_DSPI[set ::spibus]_PCSS == 1 \
+ implies CYGHWR_FREESCALE_DSPI[set ::spibus]_CS5 == 0
+ }
+
+ for { set ::spics 0 } { $::spics < 5 } { incr ::spics } {
+ cdl_interface CYGINT_FREESCALE_DSPI[set ::spibus]_CS[set ::spics] {
+ flavor bool
+ requires CYGHWR_FREESCALE_DSPI[set ::spibus]_CS[set ::spics] == 1
+ display "Use CS[set ::spics]"
+ }
+
+ cdl_component CYGHWR_FREESCALE_DSPI[set ::spibus]_CS[set ::spics] {
+ display "CS[set ::spics]"
+ flavor bool
+ default_value 0
+ cdl_option CYGHWR_FREESCALE_DSPI[set ::spibus]_CS[set ::spics]_IS {
+ display "CS[set ::spics] Inactive state Hi(1) Lo(0)"
+ flavor data
+ no_define
+ default_value { 1 }
+ legal_values { 0 1 }
+ }
+ }
+ }
+
+ cdl_component CYGHWR_DEVS_SPI_FREESCALE_DSPI[set ::spibus]_PCSIS {
+ display "Peripheral CS inactive states"
+ flavor data
+ calculated (0x0 + \
+ (get_data(CYGHWR_FREESCALE_DSPI[set ::spibus]_CS0_IS) == 1 ? 1 : 0) + \
+ (get_data(CYGHWR_FREESCALE_DSPI[set ::spibus]_CS1_IS) == 1 ? 2 : 0) + \
+ (get_data(CYGHWR_FREESCALE_DSPI[set ::spibus]_CS2_IS) == 1 ? 4 : 0) + \
+ (get_data(CYGHWR_FREESCALE_DSPI[set ::spibus]_CS3_IS) == 1 ? 8 : 0) + \
+ (get_data(CYGHWR_FREESCALE_DSPI[set ::spibus]_CS4_IS) == 1 ? 16 : 0) + \
+ (get_data(CYGHWR_FREESCALE_DSPI[set ::spibus]_CS5_IS) == 1 ? 32 : 0))
+ }
+ }
+
+ cdl_interface CYGINT_FREESCALE_DSPI[set ::spibus]_HAS_MASS {
+ description "SPI bus serves mass data device(s)."
+ }
+
+ cdl_option CYGNUM_DEVS_SPI_FREESCALE_DSPI[set ::spibus]_PUSHQUE_SIZE {
+ display "Queue buffer size"
+ description "
+ DSPI requires a command for every transfer so output
+ data must be re-packed in additional buffer prior to
+ being submitted to DMA.
+ If Queue capacity is same as DSPI FIFO size, the minimal
+ legal value, the DMA is not needed so no buffer memory
+ is allocated. Note: For every entry, byte (8 bit transfer)
+ or half word (16 bit transfer) a whole 32 bit word
+ is being allocated."
+
+ legal_values { CYGHWR_DEVS_SPI_FREESCALE_DSPI_FIFO_SIZE to 2048 }
+ flavor data
+ default_value CYGINT_FREESCALE_DSPI[set ::spibus]_HAS_MASS ? 128 : \
+ CYGHWR_DEVS_SPI_FREESCALE_DSPI_FIFO_SIZE
+ }
+
+ cdl_interface CYGINT_DEVS_SPI_DSPI[set ::spibus]_USES_DMA {
+ flavor bool
+ }
+
+ cdl_component CYGHWR_DEVS_SPI_FREESCALE_DSPI[set ::spibus]_TX_DMA_CHAN {
+ display "TX DMA channel"
+ flavor data
+ implements CYGINT_DEVS_SPI_DSPI_DMA_USE
+ implements CYGINT_DEVS_SPI_DSPI[set ::spibus]_USES_DMA
+
+ active_if CYGNUM_DEVS_SPI_FREESCALE_DSPI[set ::spibus]_PUSHQUE_SIZE > \
+ CYGHWR_DEVS_SPI_FREESCALE_DSPI_FIFO_SIZE
+ default_value 4 + [set ::spibus] * 2
+ legal_values { 0 to (CYGNUM_HAL_FREESCALE_EDMA_CHAN_NUM-1) }
+ description "DMA channel assigned to the trasmitter of SPI bus"
+
+ cdl_component CYGNUM_DEVS_SPI_FREESCALE_DSPI[set ::spibus]_TX_DMA_PRI {
+ display "Transmit DMA channel priority"
+ flavor data
+ legal_values { 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 255 }
+ default_value 255
+ description "
+ DMA can work in either round robin or preeptve arbitration
+ mode. In preemptive mode, DMA each channel has unique priority,
+ lower number meaning lower priority.
+ 255 is a phony meaning \"default channel priority\"."
+
+ cdl_option CYGNUM_DEVS_SPI_FREESCALE_DSPI[set ::spibus]_TX_DMA_ECP {
+ display "Enable channel preemption"
+ flavor data
+ legal_values { 0 1 }
+ default_value 0
+ }
+
+ cdl_option CYGNUM_DEVS_SPI_FREESCALE_DSPI[set ::spibus]_TX_DMA_DPA {
+ display "Disable preempt ability"
+ flavor data
+ legal_values { 0 1 }
+ default_value 0
+ }
+
+ }
+
+ cdl_option CYGOPT_DEVS_SPI_FREESCALE_DSPI[set ::spibus]_TCD_SECTION {
+ display "DMA TCD section"
+ flavor data
+ default_value CYGHWR_HAL_EDMA_TCD_SECTION
+
+ description "
+ Section in which will be DMA Transfer Control
+ Descriptors shall reside"
+ }
+ }
+
+ cdl_component CYGHWR_DEVS_SPI_FREESCALE_DSPI[set ::spibus]_RX_DMA_CHAN {
+ display "RX DMA channel"
+ flavor data
+ implements CYGINT_DEVS_SPI_DSPI_DMA_USE
+ implements CYGINT_DEVS_SPI_DSPI[set ::spibus]_USES_DMA
+
+ active_if CYGNUM_DEVS_SPI_FREESCALE_DSPI[set ::spibus]_PUSHQUE_SIZE > \
+ CYGHWR_DEVS_SPI_FREESCALE_DSPI_FIFO_SIZE
+ default_value 5 + [set ::spibus] * 2
+ legal_values { 0 to (CYGNUM_HAL_FREESCALE_EDMA_CHAN_NUM-1) }
+ description "DMA channel assigned to the receiver of SPI bus"
+
+ cdl_component CYGNUM_DEVS_SPI_FREESCALE_DSPI[set ::spibus]_RX_DMA_PRI {
+ display "Receive DMA channel priority"
+ flavor data
+ legal_values { 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 255 }
+ default_value 255
+ description "
+ DMA can work in either round robin or preeptve arbitration
+ mode. In preemptive mode, DMA each channel has unique priority,
+ lower number meaning lower priority.
+ 255 is a phony meaning \"default channel priority\"."
+
+ cdl_option CYGNUM_DEVS_SPI_FREESCALE_DSPI[set ::spibus]_RX_DMA_ECP {
+ display "Enable channel preemption"
+ flavor data
+ legal_values { 0 1 }
+ default_value 0
+ }
+
+ cdl_option CYGNUM_DEVS_SPI_FREESCALE_DSPI[set ::spibus]_RX_DMA_DPA {
+ display "Disable preempt ability"
+ flavor data
+ legal_values { 0 1 }
+ default_value 0
+ }
+ }
+ }
+
+ cdl_option CYGNUM_DEVS_SPI_FREESCALE_DSPI[set ::spibus]_ISR_PRI {
+ display "Interrupt priority"
+ flavor data
+ requires CYGNUM_DEVS_SPI_FREESCALE_DSPI[set ::spibus]_ISR_PRI_SP
+ calculated CYGNUM_DEVS_SPI_FREESCALE_DSPI[set ::spibus]_ISR_PRI_SP
+ description "Interrupt priority set-point is provided by HAL"
+ }
+ }
+ }
+
+ cdl_option CYGOPT_DEVS_SPI_FREESCALE_DSPI_TICK_ONLY_DROPS_CS {
+ display "Tick-only drops CS"
+ default_value 0
+
+ description "
+ eCos Reference Manual states that CS should drop prior to sending ticks,
+ but other drivers (so far) do not touch the CS. This option selects
+ between conformance with manual or compatibility with other drivers."
+ }
+
+ cdl_option CYGPKG_DEVS_SPI_FREESCALE_DSPI_DEBUG_LEVEL {
+ display "Driver debug output level"
+ flavor data
+ legal_values { 0 1 2 3 }
+ default_value 0
+ description "
+ This option specifies the level of debug data output by
+ the Freescale DSPI device driver. A value of 0 signifies
+ no debug data output; 1 signifies normal debug data
+ output; and 2 signifies maximum debug data output."
+ }
+
+
+ cdl_component CYGPKG_DEVS_SPI_FREESCALE_DSPI_OPTIONS {
+ display "Freescale DSPI driver build options"
+ flavor none
+ description "
+ Package specific build options including control over
+ compiler flags used only in building this package,
+ and details of which tests are built."
+
+ cdl_option CYGPKG_DEVS_SPI_FREESCALE_DSPI_CFLAGS_ADD {
+ display "Additional compiler flags"
+ flavor data
+ no_define
+ default_value { "" }
+ description "
+ This option modifies the set of compiler flags for
+ building the Freescale DSPI driver. These flags are used in addition
+ to the set of global flags."
+ }
+
+ cdl_option CYGPKG_DEVS_SPI_FREESCALE_DSPI_CFLAGS_REMOVE {
+ display "Suppressed compiler flags"
+ flavor data
+ no_define
+ default_value { "" }
+ description "
+ This option modifies the set of compiler flags for
+ building the Freescale DSPI driver. These flags are removed from
+ the set of global flags if present."
+ }
+
+ }
+
+ cdl_component CYGPKG_DEVS_SPI_FREESCALE_DSPI_TESTS {
+ display "Freescale DSPI tests"
+ flavor data
+ no_define
+ calculated { CYGBLD_DEVS_SPI_FREESCALE_DSPI_LOOPBACK_TEST ? "tests/spi_loopback" : "" }
+
+ cdl_option CYGBLD_DEVS_SPI_FREESCALE_DSPI_LOOPBACK_TEST {
+ display "Build Freescale DSPI loopback test"
+ flavor bool
+ no_define
+ default_value 0
+ requires { CYGHWR_DEVS_SPI_FREESCALE_DSPI0 ||
+ CYGHWR_DEVS_SPI_FREESCALE_DSPI1 ||
+ CYGHWR_DEVS_SPI_FREESCALE_DSPI2 }
+ description "
+ This option enables the building of the Freescale DSPI loopback test.
+ Refer to the comments in tests/loopback.c for details of how to
+ use this test."
+ }
+ }
+}
+# EOF spi_freescale_dspi.cdl
diff --git a/ecos/packages/devs/spi/freescale/dspi/current/include/spi_freescale_dspi.h b/ecos/packages/devs/spi/freescale/dspi/current/include/spi_freescale_dspi.h
new file mode 100644
index 0000000..f1fe610
--- /dev/null
+++ b/ecos/packages/devs/spi/freescale/dspi/current/include/spi_freescale_dspi.h
@@ -0,0 +1,207 @@
+#ifndef CYGONCE_DEVS_SPI_FREESCALE_DSPI_H
+#define CYGONCE_DEVS_SPI_FREESCALE_DSPI_H
+//=============================================================================
+//
+// spi_freescale_dspi.h
+//
+// Header definitions for Freescale DSPI driver.
+//
+//=============================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later
+// version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with eCos; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// As a special exception, if other files instantiate templates or use
+// macros or inline functions from this file, or you compile this file
+// and link it with other works to produce a work based on this file,
+// this file does not by itself cause the resulting work to be covered by
+// the GNU General Public License. However the source code for this file
+// must still be made available in accordance with section (3) of the GNU
+// General Public License v2.
+//
+// This exception does not invalidate any other reasons why a work based
+// on this file might be covered by the GNU General Public License.
+// -------------------------------------------
+// ####ECOSGPLCOPYRIGHTEND####
+//=============================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): ilijak
+// Date: 2011-11-03
+// Purpose: Freescale DSPI driver definitions.
+// Description:
+// Usage: #include <cyg/io/spi_freescale_dspi.h>
+//
+//####DESCRIPTIONEND####
+//
+//=============================================================================
+
+#include <pkgconf/hal.h>
+#include <pkgconf/io_spi.h>
+#include <pkgconf/devs_spi_freescale_dspi.h>
+#include <pkgconf/hal_freescale_edma.h>
+
+#include <cyg/infra/cyg_type.h>
+#include <cyg/hal/drv_api.h>
+#include <cyg/io/spi.h>
+#include <cyg/hal/freescale_edma.h>
+#include <cyg/io/spi_freescale_dspi_io.h>
+
+//-----------------------------------------------------------------------------
+// Macro for defining a SPI device and attaching it to the appropriate bus.
+//
+// _name_ is the name of the SPI device. This will be used to reference a
+// data structure of type cyg_spi_device which can be passed to the
+// SPI driver API without needing a cast.
+// _bus_ is the bus number to which this device is attached (0, 1 or 2).
+// _csnum_ is the chip select line used for this device, numbered from 0.
+// _fmsz_ is set device SPI frame size (bits)
+// _clpol_ is the SPI bus clock polarity used by the device. This must be
+// set to 1 if clock inactive state is high, 0 if clock inactive
+// state is low.
+// _clpha_ is the SPI bus clock phase used by the device.
+// _brate_ is the SPI bus clock baud rate used by the device, measured in Hz.
+// _csup_dly_ is the minimum delay between chip select assert and transfer
+// start, measured in microseconds.
+// _csdw_dly_ is the minimum delay between transfer end and chip select deassert,
+// measured in delay units.
+// _trbt_dly_ is the minimum delay between consecutive transfers.
+// _dlu_ is delay unit in ns
+// _dbr_ is enabling double baud rate feature
+
+
+#define CYGNUM_DSPI_DELAY_UNIT(__val) (__val/10)
+
+#define CYG_SPI_BUS_NAME(_b_) cyg_spi_dspi_bus ## _b_
+
+#define CYG_DEVS_SPI_FREESCALE_DSPI_DEVICE( \
+ _name_, _bus_, _csnum_, _fmsz_, _clpol_, _clpha_, _brate_, _csup_dly_, _csdw_dly_, _trbt_dly_, _dlu_, _dbr_ \
+) \
+ cyg_spi_freescale_dspi_device_t _name_ ##_fs_dspi CYG_SPI_DEVICE_ON_BUS(_bus_) = { \
+{ .spi_bus = (cyg_spi_bus*) &CYG_SPI_BUS_NAME(_bus_) }, \
+ .dev_num = _csnum_, \
+ .clocking.bus_16bit = _fmsz_ > 8 ? 1 : 0, \
+ .clocking.frame_size = _fmsz_, \
+ .clocking.cl_pol = _clpol_, \
+ .clocking.cl_pha = _clpha_, \
+ .clocking.cl_brate = _brate_, \
+ .clocking.cs_up_udly = _csup_dly_, \
+ .clocking.cs_dw_udly = _csdw_dly_, \
+ .clocking.tr_bt_udly = _trbt_dly_, \
+ .clocking.dl_unit = CYGNUM_DSPI_DELAY_UNIT(_dlu_), \
+ .clocking.cl_dbr = _dbr_, \
+ .clocking.dspi_ctar = 0 \
+}; \
+extern cyg_spi_device _name_ __attribute__((alias ( #_name_ "_fs_dspi" )))
+
+enum { SPI_DMA_CHAN_TX_I, SPI_DMA_CHAN_RX_I };
+
+//-----------------------------------------------------------------------------
+// Freescale DSPI bus configuration and state.
+
+typedef struct cyg_spi_freescale_dspi_bus_setup_s
+{
+ cyghwr_devs_freescale_dspi_t* dspi_p; // Base address of SPI register block.
+ cyghwr_hal_freescale_dma_set_t* dma_set_p; // DMA configuration block.
+ cyg_vector_t intr_num; // DSPI interrupt vector
+ cyg_priority_t intr_prio; // Interrupt priority
+ cyg_uint32 mcr_opt ; // Module Configuratyon Register options
+ const cyg_uint32* spi_pin_list_p; // List of GPIOs used by the SPI interface.
+ const cyg_uint32* cs_pin_list_p; // List of GPIOs used as chip selects.
+ cyg_uint16 clk_gate; // Clock gate
+ cyg_uint8 cs_pin_num; // Number of chip selects for this bus.
+} cyg_spi_freescale_dspi_bus_setup_t;
+
+#define SPI_DMA_CHAN_I(__dma_set,__rt) (__dma_set->chan_p[SPI_DMA_CHAN_ ## __rt ## _I].dma_chan_i)
+
+typedef struct cyg_spi_freescale_dspi_bus_s
+{
+ // ---- Upper layer data ----
+ cyg_spi_bus spi_bus; // Upper layer SPI bus data.
+
+ // ---- Bus configuration constants ----
+ const cyg_spi_freescale_dspi_bus_setup_t* setup_p;
+ // ---- Driver state (private) ----
+ // DMA transfer control descriptors
+ const cyghwr_hal_freescale_edma_tcd_t* tx_dma_tcd_ini_p; // TCD init.
+ const cyghwr_hal_freescale_edma_tcd_t* rx_dma_tcd_ini_p; // data
+ volatile cyghwr_hal_freescale_edma_tcd_t* rx_dma_tcd_p; // DMA TCD (RX)
+ volatile cyghwr_hal_freescale_edma_tcd_t* tx_dma_tcd_p; // DMA TCD (TX)
+ volatile cyg_uint32* pushque_p; // Tx command queue
+ cyg_uint16 pushque_n; // Tx command buffer size
+ cyg_uint8 txfifo_n; // TxFIFO size
+ cyg_uint8 rxfifo_n; // RxFIFO size
+ cyg_interrupt intr_data; // Interrupt state
+ cyg_handle_t intr_handle; // Interrupt handle
+ cyg_drv_mutex_t transfer_mutex; // Transfer mutex.
+ cyg_drv_cond_t transfer_done; // Transfer condition variable.
+ cyg_uint32 clock_freq; // Clock provided by hal
+} cyg_spi_freescale_dspi_bus_t;
+
+//-----------------------------------------------------------------------------
+// Freescale DSPI device.
+
+typedef struct cyg_freescale_dspi_clocking_s {
+ cyg_uint32 dspi_ctar; // DSPI Clock and Transfer Attributes Rregister shadow.
+ cyg_uint32 cl_brate; // Clock baud rate.
+ cyg_uint8 bus_16bit; // Use 16 bit (1) or 8 bit (0) transfers.
+ cyg_uint8 cl_pol; // Clock polarity (0 or 1).
+ cyg_uint8 cl_pha; // Clock phase (0 or 1).
+ cyg_uint8 cl_dbr; // Use double baud-rate feature if needed
+ cyg_uint8 cs_up_udly; // Minimum delay in us/ns between CS up and transfer start.
+ cyg_uint8 cs_dw_udly; // Minimum delay in us/ns between transfer end and CS down.
+ cyg_uint8 tr_bt_udly; // Minimum delay in us/ns between two transfers.
+ cyg_uint8 dl_unit; // Delay unit (1/10 * ns)
+ cyg_uint8 lsb_first; // LSbit shifted first.
+ cyg_uint8 frame_size; // Device SPI frame size (bits).
+} cyg_freescale_dspi_clocking_t;;
+
+typedef struct cyg_spi_freescale_dspi_device_s
+{
+ // ---- Upper layer data ----
+ cyg_spi_device spi_device; // Upper layer SPI device data.
+
+ // ---- Device setup (user configurable) ----
+ cyg_freescale_dspi_clocking_t clocking;
+ cyg_uint8 dev_num; // Device SPI select.
+ cyg_uint8 chip_sel;
+ // ---- Device state (private) ----
+} cyg_spi_freescale_dspi_device_t;
+
+//-----------------------------------------------------------------------------
+// Exported bus data structures.
+
+#ifdef CYGHWR_DEVS_SPI_FREESCALE_DSPI0
+externC cyg_spi_freescale_dspi_bus_t cyg_spi_dspi_bus0;
+#endif
+
+#ifdef CYGHWR_DEVS_SPI_FREESCALE_DSPI1
+externC cyg_spi_freescale_dspi_bus_t cyg_spi_dspi_bus1;
+#endif
+
+#ifdef CYGHWR_DEVS_SPI_FREESCALE_DSPI2
+externC cyg_spi_freescale_dspi_bus_t cyg_spi_dspi_bus2;
+#endif
+
+__externC void cyghwr_devs_freescale_dspi_diag(cyg_spi_freescale_dspi_bus_t* spi_bus_p);
+__externC void cyghwr_devs_freescale_dspi_diag_array(char* name_p,
+ volatile cyg_uint32* fifo_p,
+ cyg_uint32 fifo_n);
+
+//=============================================================================
+#endif // CYGONCE_DEVS_SPI_FREESCALE_DSPI_H
diff --git a/ecos/packages/devs/spi/freescale/dspi/current/include/spi_freescale_dspi_buses.inl b/ecos/packages/devs/spi/freescale/dspi/current/include/spi_freescale_dspi_buses.inl
new file mode 100644
index 0000000..5fb16f2
--- /dev/null
+++ b/ecos/packages/devs/spi/freescale/dspi/current/include/spi_freescale_dspi_buses.inl
@@ -0,0 +1,586 @@
+#ifndef SPI_FREESCALE_DSPI_BUSES_INL
+#define SPI_FREESCALE_DSPI_BUSES_INL
+//=============================================================================
+//
+// spi_freescale_dspi_buses.inl
+//
+// SPI bus instantiation for Freescale DSPI
+//
+//=============================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2011, 2013 Free Software Foundation, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later
+// version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with eCos; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// As a special exception, if other files instantiate templates or use
+// macros or inline functions from this file, or you compile this file
+// and link it with other works to produce a work based on this file,
+// this file does not by itself cause the resulting work to be covered by
+// the GNU General Public License. However the source code for this file
+// must still be made available in accordance with section (3) of the GNU
+// General Public License v2.
+//
+// This exception does not invalidate any other reasons why a work based
+// on this file might be covered by the GNU General Public License.
+// -------------------------------------------
+// ####ECOSGPLCOPYRIGHTEND####
+//=============================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): ilijak
+// Date: 2011-11-09
+// Purpose: Freescale DSPI DSPI bus instantiation
+//
+//####DESCRIPTIONEND####
+//
+//=============================================================================
+
+#define PUSHQUE_ALIGN CYGBLD_ATTRIB_ALIGN(4)
+
+#define DSPI_DMA_BANDWIDTH FREESCALE_EDMA_CSR_BWC_0
+
+//-----------------------------------------------------------------------------
+// Instantiate the bus state data structures.
+
+// Some auxiliary macros
+
+#if (CYG_BYTEORDER == CYG_MSBFIRST) // AKA Big endian
+#define EDMA_TCD_SADDR(__bus) \
+ .saddr = (void *)(((unsigned int)&CYGADDR_IO_SPI_FREESCALE_DSPI ## __bus ## _P->popr) + 3)
+#else // AKA Little endian
+#define EDMA_TCD_SADDR(__bus) \
+ .saddr = (cyg_uint32 *)&CYGADDR_IO_SPI_FREESCALE_DSPI ## __bus ## _P->popr
+#endif
+
+#define DSPI_EDMA_CHAN_SET(__bus) \
+static volatile cyg_uint32 \
+dspi ## __bus ## _pushque[CYGNUM_DEVS_SPI_FREESCALE_DSPI ## __bus ## _PUSHQUE_SIZE+4] \
+PUSHQUE_ALIGN EDMA_RAM_BUF_SECTION; \
+ \
+static const cyghwr_hal_freescale_dma_chan_set_t dspi ## __bus ## _dma_chan[2] = \
+{ \
+ { \
+ .dma_src = FREESCALE_DMAMUX_SRC_SPI ## __bus ## _TX \
+ | FREESCALE_DMAMUX_CHCFG_ENBL_M, \
+ .dma_chan_i = CYGHWR_DEVS_SPI_FREESCALE_DSPI ## __bus ## _TX_DMA_CHAN, \
+ .dma_prio = CYGNUM_DEVS_SPI_FREESCALE_DSPI ## __bus ## _TX_DMA_PRI, \
+ }, \
+ { \
+ .dma_src = FREESCALE_DMAMUX_SRC_SPI ## __bus ## _RX \
+ | FREESCALE_DMAMUX_CHCFG_ENBL_M, \
+ .dma_chan_i = CYGHWR_DEVS_SPI_FREESCALE_DSPI ## __bus ## _RX_DMA_CHAN, \
+ .dma_prio = CYGNUM_DEVS_SPI_FREESCALE_DSPI ## __bus ## _RX_DMA_PRI, \
+ } \
+}; \
+ \
+static cyghwr_hal_freescale_dma_set_t dspi ## __bus ## _dma_set = { \
+ .chan_p = dspi ## __bus ## _dma_chan, \
+ .chan_n = 2 \
+}; \
+ \
+static const cyghwr_hal_freescale_edma_tcd_t dspi ## __bus ## _dma_tcd_tx_ini = \
+{ \
+ .saddr = (cyg_uint32 *) dspi ## __bus ## _pushque, \
+ .soff = 4, \
+ .attr = FREESCALE_EDMA_ATTR_SSIZE(FREESCALE_EDMA_ATTR_SIZE_32) | \
+ FREESCALE_EDMA_ATTR_DSIZE(FREESCALE_EDMA_ATTR_SIZE_32) | \
+ FREESCALE_EDMA_ATTR_SMOD(0) | \
+ FREESCALE_EDMA_ATTR_DMOD(0), \
+ .daddr = (cyg_uint32 *) \
+ &CYGADDR_IO_SPI_FREESCALE_DSPI ## __bus ## _P->pushr, \
+ .doff = 0, \
+ .nbytes.mlno = 4, \
+ .slast = 0, \
+ .citer.elinkno = 1, \
+ .dlast_sga.dlast = 0, \
+ .biter.elinkno = 1, \
+ .csr = DSPI_DMA_BANDWIDTH \
+}; \
+ \
+static const cyghwr_hal_freescale_edma_tcd_t dspi ## __bus ## _dma_tcd_rx_ini = \
+{ \
+ EDMA_TCD_SADDR(__bus), \
+ .soff = 0, \
+ .attr = FREESCALE_EDMA_ATTR_SSIZE(FREESCALE_EDMA_ATTR_SIZE_32) | \
+ FREESCALE_EDMA_ATTR_DSIZE(FREESCALE_EDMA_ATTR_SIZE_32) | \
+ FREESCALE_EDMA_ATTR_SMOD(0) | \
+ FREESCALE_EDMA_ATTR_DMOD(0), \
+ .daddr = NULL, \
+ .doff = 4, \
+ .nbytes.mlno = 4, \
+ .slast = 0, \
+ .citer.elinkno = 1, \
+ .dlast_sga.dlast = 0, \
+ .biter.elinkno = 1, \
+ .csr = DSPI_DMA_BANDWIDTH \
+}
+
+#define DSPI_EDMA_SET_P_YES(__bus) .dma_set_p = &dspi ## __bus ## _dma_set
+#define DSPI_EDMA_SET_P_NULL(__bus) .dma_set_p = NULL
+
+#define DSPI_EDMA_TCD_YES(__bus) \
+ .tx_dma_tcd_p = &CYGHWR_IO_FREESCALE_EDMA0_P-> \
+ tcd[CYGHWR_DEVS_SPI_FREESCALE_DSPI ## __bus ## _TX_DMA_CHAN], \
+ .rx_dma_tcd_p = &CYGHWR_IO_FREESCALE_EDMA0_P-> \
+ tcd[CYGHWR_DEVS_SPI_FREESCALE_DSPI ## __bus ## _RX_DMA_CHAN], \
+ .tx_dma_tcd_ini_p = &dspi ## __bus ## _dma_tcd_tx_ini, \
+ .rx_dma_tcd_ini_p = &dspi ## __bus ## _dma_tcd_rx_ini, \
+ .pushque_p = dspi ## __bus ## _pushque
+
+#define DSPI_EDMA_TCD_NULL(__bus) \
+ .tx_dma_tcd_p = NULL, \
+ .rx_dma_tcd_p = NULL, \
+ .tx_dma_tcd_ini_p = NULL, \
+ .rx_dma_tcd_ini_p = NULL, \
+ .pushque_p = NULL
+
+// End DSPI_EDMA
+
+#define DSPI_BUS_SETUP(__bus) \
+static const cyg_spi_freescale_dspi_bus_setup_t dspi ## __bus ## _setup = { \
+ .dspi_p = CYGADDR_IO_SPI_FREESCALE_DSPI ## __bus ## _P, \
+ .intr_num = CYGNUM_HAL_INTERRUPT_SPI ## __bus, \
+ .intr_prio = CYGNUM_DEVS_SPI_FREESCALE_DSPI ## __bus ## _ISR_PRI, \
+ .spi_pin_list_p = spi ## __bus ## _pins, \
+ .cs_pin_list_p = spi ## __bus ## _cs_pins, \
+ .clk_gate = CYGHWR_IO_FREESCALE_DSPI ## __bus ## _CLK, \
+ .cs_pin_num = sizeof(spi ## __bus ## _cs_pins)/ \
+ sizeof(spi ## __bus ## _cs_pins[0]), \
+ .mcr_opt = CYGHWR_FREESCALE_DSPI ## __bus ## _MCR_PCSSE | \
+ FREESCALE_DSPI_MCR_PCSIS( \
+ CYGHWR_DEVS_SPI_FREESCALE_DSPI ## __bus ## _PCSIS), \
+ DSPI ## __bus ## _EDMA_SET_P \
+}
+
+#define DSPI_BUS(__bus) \
+cyg_spi_freescale_dspi_bus_t cyg_spi_dspi_bus ## __bus = { \
+ .spi_bus.spi_transaction_begin = dspi_transaction_begin, \
+ .spi_bus.spi_transaction_transfer = dspi_transaction_transfer, \
+ .spi_bus.spi_transaction_tick = dspi_transaction_tick, \
+ .spi_bus.spi_transaction_end = dspi_transaction_end, \
+ .spi_bus.spi_get_config = dspi_get_config, \
+ .spi_bus.spi_set_config = dspi_set_config, \
+ .setup_p = &dspi ## __bus ## _setup, \
+ DSPI ## __bus ## _EDMA_TCD, \
+ .pushque_n = CYGNUM_DEVS_SPI_FREESCALE_DSPI ## __bus ## _PUSHQUE_SIZE, \
+ .txfifo_n = CYGHWR_DEVS_SPI_FREESCALE_DSPI_FIFO_SIZE, \
+ .rxfifo_n = CYGHWR_DEVS_SPI_FREESCALE_DSPI_FIFO_SIZE \
+}
+
+#define DSPI_BUS_PINS(__bus) \
+static const cyg_uint32 spi ## __bus ## _pins[] = { \
+ CYGHWR_IO_FREESCALE_SPI ## __bus ## _PIN_SIN, \
+ CYGHWR_IO_FREESCALE_SPI ## __bus ## _PIN_SOUT, \
+ CYGHWR_IO_FREESCALE_SPI ## __bus ## _PIN_SCK \
+}
+
+// DSPI BUS Instances =======================================================
+
+// DSPI BUS 0 ================================================================
+#ifdef CYGHWR_DEVS_SPI_FREESCALE_DSPI0
+
+#define CYGBLD_DSPI0_TCD_SECTION \
+ CYGBLD_ATTRIB_SECTION(CYGOPT_DEVS_SPI_FREESCALE_DSPI0_TCD_SECTION)
+
+#ifdef CYHGWR_DEVS_SPI_FREESCALE_DSPI0_PCSS
+#define CYGHWR_FREESCALE_DSPI0_MCR_PCSSE FREESCALE_DSPI_MCR_PCSSE_M
+#else
+#define CYGHWR_FREESCALE_DSPI0_MCR_PCSSE 0
+#endif
+
+// SPI chip select pins.
+static const cyg_uint32 spi0_cs_pins[] = {
+#ifdef CYGHWR_FREESCALE_DSPI0_CS0
+ CYGHWR_IO_FREESCALE_SPI0_PIN_CS0,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI0_CS1
+ CYGHWR_IO_FREESCALE_SPI0_PIN_CS1,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI0_CS2
+ CYGHWR_IO_FREESCALE_SPI0_PIN_CS2,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI0_CS3
+ CYGHWR_IO_FREESCALE_SPI0_PIN_CS3,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI0_CS4
+ CYGHWR_IO_FREESCALE_SPI0_PIN_CS4,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI0_CS5
+ CYGHWR_IO_FREESCALE_SPI0_PIN_CS5
+#endif
+};
+
+#ifdef CYGINT_DEVS_SPI_DSPI0_USES_DMA
+ DSPI_EDMA_CHAN_SET(0);
+# define DSPI0_EDMA_SET_P DSPI_EDMA_SET_P_YES(0)
+# define DSPI0_EDMA_TCD DSPI_EDMA_TCD_YES(0)
+#else
+# define DSPI0_EDMA_SET_P DSPI_EDMA_SET_P_NULL(0)
+# define DSPI0_EDMA_TCD DSPI_EDMA_TCD_NULL(0)
+#endif // CYGINT_DEVS_SPI_DSPI0_USES_DMA
+
+DSPI_BUS_PINS(0);
+DSPI_BUS_SETUP(0);
+DSPI_BUS(0);
+
+#endif // CYGHWR_DEVS_SPI_FREESCALE_DSPI0
+
+// DSPI BUS 1 ================================================================
+#ifdef CYGHWR_DEVS_SPI_FREESCALE_DSPI1
+
+#define CYGBLD_DSPI1_TCD_SECTION \
+ CYGBLD_ATTRIB_SECTION(CYGOPT_DEVS_SPI_FREESCALE_DSPI1_TCD_SECTION)
+
+#ifdef CYHGWR_DEVS_SPI_FREESCALE_DSPI1_PCSS
+#define CYGHWR_FREESCALE_DSPI1_MCR_PCSSE FREESCALE_DSPI_MCR_PCSSE_M
+#else
+#define CYGHWR_FREESCALE_DSPI1_MCR_PCSSE 0
+#endif
+
+// SPI chip select pins.
+static const cyg_uint32 spi1_cs_pins[] = {
+#ifdef CYGHWR_FREESCALE_DSPI1_CS0
+ CYGHWR_IO_FREESCALE_SPI1_PIN_CS0,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI1_CS1
+ CYGHWR_IO_FREESCALE_SPI1_PIN_CS1,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI1_CS2
+ CYGHWR_IO_FREESCALE_SPI1_PIN_CS2,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI1_CS3
+ CYGHWR_IO_FREESCALE_SPI1_PIN_CS3,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI1_CS4
+ CYGHWR_IO_FREESCALE_SPI1_PIN_CS4,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI1_CS5
+ CYGHWR_IO_FREESCALE_SPI1_PIN_CS5
+#endif
+};
+
+#ifdef CYGINT_DEVS_SPI_DSPI1_USES_DMA
+ DSPI_EDMA_CHAN_SET(1);
+# define DSPI1_EDMA_SET_P DSPI_EDMA_SET_P_YES(1)
+# define DSPI1_EDMA_TCD DSPI_EDMA_TCD_YES(1)
+#else
+# define DSPI1_EDMA_SET_P DSPI_EDMA_SET_P_NULL(1)
+# define DSPI1_EDMA_TCD DSPI_EDMA_TCD_NULL(1)
+#endif // CYGINT_DEVS_SPI_DSPI1_USES_DMA
+
+DSPI_BUS_PINS(1);
+DSPI_BUS_SETUP(1);
+DSPI_BUS(1);
+
+#endif // CYGHWR_DEVS_SPI_FREESCALE_DSPI1
+
+// DSPI BUS 2 ================================================================
+#ifdef CYGHWR_DEVS_SPI_FREESCALE_DSPI2
+
+#define CYGBLD_DSPI2_TCD_SECTION \
+ CYGBLD_ATTRIB_SECTION(CYGOPT_DEVS_SPI_FREESCALE_DSPI2_TCD_SECTION)
+
+#ifdef CYHGWR_DEVS_SPI_FREESCALE_DSPI2_PCSS
+#define CYGHWR_FREESCALE_DSPI2_MCR_PCSSE FREESCALE_DSPI_MCR_PCSSE_M
+#else
+#define CYGHWR_FREESCALE_DSPI2_MCR_PCSSE 0
+#endif
+
+// SPI chip select pins.
+static const cyg_uint32 spi2_cs_pins[] = {
+#ifdef CYGHWR_FREESCALE_DSPI2_CS0
+ CYGHWR_IO_FREESCALE_SPI2_PIN_CS0,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI2_CS1
+ CYGHWR_IO_FREESCALE_SPI2_PIN_CS1,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI2_CS2
+ CYGHWR_IO_FREESCALE_SPI2_PIN_CS2,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI2_CS3
+ CYGHWR_IO_FREESCALE_SPI2_PIN_CS3,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI2_CS4
+ CYGHWR_IO_FREESCALE_SPI2_PIN_CS4,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI2_CS5
+ CYGHWR_IO_FREESCALE_SPI2_PIN_CS5
+#endif
+};
+
+#ifdef CYGINT_DEVS_SPI_DSPI2_USES_DMA
+ DSPI_EDMA_CHAN_SET(2);
+# define DSPI2_EDMA_SET_P DSPI_EDMA_SET_P_YES(2)
+# define DSPI2_EDMA_TCD DSPI_EDMA_TCD_YES(2)
+#else
+# define DSPI2_EDMA_SET_P DSPI_EDMA_SET_P_NULL(2)
+# define DSPI2_EDMA_TCD DSPI_EDMA_TCD_NULL(2)
+#endif // CYGINT_DEVS_SPI_DSPI2_USES_DMA
+
+DSPI_BUS_PINS(2);
+DSPI_BUS_SETUP(2);
+DSPI_BUS(2);
+
+#endif // CYGHWR_DEVS_SPI_FREESCALE_DSPI2
+
+// DSPI BUS 3 ================================================================
+#ifdef CYGHWR_DEVS_SPI_FREESCALE_DSPI3
+
+#define CYGBLD_DSPI3_TCD_SECTION \
+ CYGBLD_ATTRIB_SECTION(CYGOPT_DEVS_SPI_FREESCALE_DSPI3_TCD_SECTION)
+
+#ifdef CYHGWR_DEVS_SPI_FREESCALE_DSPI3_PCSS
+#define CYGHWR_FREESCALE_DSPI3_MCR_PCSSE FREESCALE_DSPI_MCR_PCSSE_M
+#else
+#define CYGHWR_FREESCALE_DSPI3_MCR_PCSSE 0
+#endif
+
+// SPI chip select pins.
+static const cyg_uint32 spi3_cs_pins[] = {
+#ifdef CYGHWR_FREESCALE_DSPI3_CS0
+ CYGHWR_IO_FREESCALE_SPI3_PIN_CS0,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI3_CS1
+ CYGHWR_IO_FREESCALE_SPI3_PIN_CS1,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI3_CS2
+ CYGHWR_IO_FREESCALE_SPI3_PIN_CS2,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI3_CS3
+ CYGHWR_IO_FREESCALE_SPI3_PIN_CS3,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI3_CS4
+ CYGHWR_IO_FREESCALE_SPI3_PIN_CS4,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI3_CS5
+ CYGHWR_IO_FREESCALE_SPI3_PIN_CS5
+#endif
+};
+
+#ifdef CYGINT_DEVS_SPI_DSPI3_USES_DMA
+ DSPI_EDMA_CHAN_SET(3);
+# define DSPI3_EDMA_SET_P DSPI_EDMA_SET_P_YES(3)
+# define DSPI3_EDMA_TCD DSPI_EDMA_TCD_YES(3)
+#else
+# define DSPI3_EDMA_SET_P DSPI_EDMA_SET_P_NULL(3)
+# define DSPI3_EDMA_TCD DSPI_EDMA_TCD_NULL(3)
+#endif // CYGINT_DEVS_SPI_DSPI3_USES_DMA
+
+DSPI_BUS_PINS(3);
+DSPI_BUS_SETUP(3);
+DSPI_BUS(3);
+
+#endif // CYGHWR_DEVS_SPI_FREESCALE_DSPI3
+
+// DSPI BUS 4 ================================================================
+#ifdef CYGHWR_DEVS_SPI_FREESCALE_DSPI4
+
+#define CYGBLD_DSPI4_TCD_SECTION \
+ CYGBLD_ATTRIB_SECTION(CYGOPT_DEVS_SPI_FREESCALE_DSPI4_TCD_SECTION)
+
+#ifdef CYHGWR_DEVS_SPI_FREESCALE_DSPI4_PCSS
+#define CYGHWR_FREESCALE_DSPI4_MCR_PCSSE FREESCALE_DSPI_MCR_PCSSE_M
+#else
+#define CYGHWR_FREESCALE_DSPI4_MCR_PCSSE 0
+#endif
+
+// SPI chip select pins.
+static const cyg_uint32 spi4_cs_pins[] = {
+#ifdef CYGHWR_FREESCALE_DSPI4_CS0
+ CYGHWR_IO_FREESCALE_SPI4_PIN_CS0,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI4_CS1
+ CYGHWR_IO_FREESCALE_SPI4_PIN_CS1,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI4_CS2
+ CYGHWR_IO_FREESCALE_SPI4_PIN_CS2,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI4_CS3
+ CYGHWR_IO_FREESCALE_SPI4_PIN_CS3,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI4_CS4
+ CYGHWR_IO_FREESCALE_SPI4_PIN_CS4,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI4_CS5
+ CYGHWR_IO_FREESCALE_SPI4_PIN_CS5
+#endif
+};
+
+#ifdef CYGINT_DEVS_SPI_DSPI4_USES_DMA
+ DSPI_EDMA_CHAN_SET(4);
+# define DSPI4_EDMA_SET_P DSPI_EDMA_SET_P_YES(4)
+# define DSPI4_EDMA_TCD DSPI_EDMA_TCD_YES(4)
+#else
+# define DSPI4_EDMA_SET_P DSPI_EDMA_SET_P_NULL(4)
+# define DSPI4_EDMA_TCD DSPI_EDMA_TCD_NULL(4)
+#endif // CYGINT_DEVS_SPI_DSPI4_USES_DMA
+
+DSPI_BUS_PINS(4);
+DSPI_BUS_SETUP(4);
+DSPI_BUS(4);
+
+#endif // CYGHWR_DEVS_SPI_FREESCALE_DSPI4
+
+// DSPI BUS 5 ================================================================
+#ifdef CYGHWR_DEVS_SPI_FREESCALE_DSPI5
+
+#define CYGBLD_DSPI5_TCD_SECTION \
+ CYGBLD_ATTRIB_SECTION(CYGOPT_DEVS_SPI_FREESCALE_DSPI5_TCD_SECTION)
+
+#ifdef CYHGWR_DEVS_SPI_FREESCALE_DSPI5_PCSS
+#define CYGHWR_FREESCALE_DSPI5_MCR_PCSSE FREESCALE_DSPI_MCR_PCSSE_M
+#else
+#define CYGHWR_FREESCALE_DSPI5_MCR_PCSSE 0
+#endif
+
+// SPI chip select pins.
+static const cyg_uint32 spi5_cs_pins[] = {
+#ifdef CYGHWR_FREESCALE_DSPI5_CS0
+ CYGHWR_IO_FREESCALE_SPI5_PIN_CS0,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI5_CS1
+ CYGHWR_IO_FREESCALE_SPI5_PIN_CS1,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI5_CS2
+ CYGHWR_IO_FREESCALE_SPI5_PIN_CS2,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI5_CS3
+ CYGHWR_IO_FREESCALE_SPI5_PIN_CS3,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI5_CS4
+ CYGHWR_IO_FREESCALE_SPI5_PIN_CS4,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI5_CS5
+ CYGHWR_IO_FREESCALE_SPI5_PIN_CS5
+#endif
+};
+
+#ifdef CYGINT_DEVS_SPI_DSPI5_USES_DMA
+ DSPI_EDMA_CHAN_SET(5);
+# define DSPI5_EDMA_SET_P DSPI_EDMA_SET_P_YES(5)
+# define DSPI5_EDMA_TCD DSPI_EDMA_TCD_YES(5)
+#else
+# define DSPI5_EDMA_SET_P DSPI_EDMA_SET_P_NULL(5)
+# define DSPI5_EDMA_TCD DSPI_EDMA_TCD_NULL(5)
+#endif // CYGINT_DEVS_SPI_DSPI5_USES_DMA
+
+DSPI_BUS_PINS(5);
+DSPI_BUS_SETUP(5);
+DSPI_BUS(5);
+
+#endif // CYGHWR_DEVS_SPI_FREESCALE_DSPI5
+
+// DSPI BUS 6 ================================================================
+#ifdef CYGHWR_DEVS_SPI_FREESCALE_DSPI6
+
+#define CYGBLD_DSPI6_TCD_SECTION \
+ CYGBLD_ATTRIB_SECTION(CYGOPT_DEVS_SPI_FREESCALE_DSPI6_TCD_SECTION)
+
+#ifdef CYHGWR_DEVS_SPI_FREESCALE_DSPI6_PCSS
+#define CYGHWR_FREESCALE_DSPI6_MCR_PCSSE FREESCALE_DSPI_MCR_PCSSE_M
+#else
+#define CYGHWR_FREESCALE_DSPI6_MCR_PCSSE 0
+#endif
+
+// SPI chip select pins.
+static const cyg_uint32 spi6_cs_pins[] = {
+#ifdef CYGHWR_FREESCALE_DSPI6_CS0
+ CYGHWR_IO_FREESCALE_SPI6_PIN_CS0,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI6_CS1
+ CYGHWR_IO_FREESCALE_SPI6_PIN_CS1,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI6_CS2
+ CYGHWR_IO_FREESCALE_SPI6_PIN_CS2,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI6_CS3
+ CYGHWR_IO_FREESCALE_SPI6_PIN_CS3,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI6_CS4
+ CYGHWR_IO_FREESCALE_SPI6_PIN_CS4,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI6_CS5
+ CYGHWR_IO_FREESCALE_SPI6_PIN_CS5
+#endif
+};
+
+#ifdef CYGINT_DEVS_SPI_DSPI6_USES_DMA
+ DSPI_EDMA_CHAN_SET(6);
+# define DSPI6_EDMA_SET_P DSPI_EDMA_SET_P_YES(6)
+# define DSPI6_EDMA_TCD DSPI_EDMA_TCD_YES(6)
+#else
+# define DSPI6_EDMA_SET_P DSPI_EDMA_SET_P_NULL(6)
+# define DSPI6_EDMA_TCD DSPI_EDMA_TCD_NULL(6)
+#endif // CYGINT_DEVS_SPI_DSPI6_USES_DMA
+
+DSPI_BUS_PINS(6);
+DSPI_BUS_SETUP(6);
+DSPI_BUS(6);
+
+#endif // CYGHWR_DEVS_SPI_FREESCALE_DSPI6
+
+// DSPI BUS 7 ================================================================
+#ifdef CYGHWR_DEVS_SPI_FREESCALE_DSPI7
+
+#define CYGBLD_DSPI7_TCD_SECTION \
+ CYGBLD_ATTRIB_SECTION(CYGOPT_DEVS_SPI_FREESCALE_DSPI7_TCD_SECTION)
+
+#ifdef CYHGWR_DEVS_SPI_FREESCALE_DSPI7_PCSS
+#define CYGHWR_FREESCALE_DSPI7_MCR_PCSSE FREESCALE_DSPI_MCR_PCSSE_M
+#else
+#define CYGHWR_FREESCALE_DSPI7_MCR_PCSSE 0
+#endif
+
+// SPI chip select pins.
+static const cyg_uint32 spi7_cs_pins[] = {
+#ifdef CYGHWR_FREESCALE_DSPI7_CS0
+ CYGHWR_IO_FREESCALE_SPI7_PIN_CS0,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI7_CS1
+ CYGHWR_IO_FREESCALE_SPI7_PIN_CS1,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI7_CS2
+ CYGHWR_IO_FREESCALE_SPI7_PIN_CS2,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI7_CS3
+ CYGHWR_IO_FREESCALE_SPI7_PIN_CS3,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI7_CS4
+ CYGHWR_IO_FREESCALE_SPI7_PIN_CS4,
+#endif
+#ifdef CYGHWR_FREESCALE_DSPI7_CS5
+ CYGHWR_IO_FREESCALE_SPI7_PIN_CS5
+#endif
+};
+
+#ifdef CYGINT_DEVS_SPI_DSPI7_USES_DMA
+ DSPI_EDMA_CHAN_SET(7);
+# define DSPI7_EDMA_SET_P DSPI_EDMA_SET_P_YES(7)
+# define DSPI7_EDMA_TCD DSPI_EDMA_TCD_YES(7)
+#else
+# define DSPI7_EDMA_SET_P DSPI_EDMA_SET_P_NULL(7)
+# define DSPI7_EDMA_TCD DSPI_EDMA_TCD_NULL(7)
+#endif // CYGINT_DEVS_SPI_DSPI7_USES_DMA
+
+DSPI_BUS_PINS(7);
+DSPI_BUS_SETUP(7);
+DSPI_BUS(7);
+
+#endif // CYGHWR_DEVS_SPI_FREESCALE_DSPI7
+
+//=============================================================================
+#endif // SPI_FREESCALE_DSPI_BUSES_INL
diff --git a/ecos/packages/devs/spi/freescale/dspi/current/include/spi_freescale_dspi_io.h b/ecos/packages/devs/spi/freescale/dspi/current/include/spi_freescale_dspi_io.h
new file mode 100644
index 0000000..798160e
--- /dev/null
+++ b/ecos/packages/devs/spi/freescale/dspi/current/include/spi_freescale_dspi_io.h
@@ -0,0 +1,292 @@
+#ifndef CYGONCE_DEVS_SPI_FREESCALE_DSPI_IO_H
+#define CYGONCE_DEVS_SPI_FREESCALE_DSPI_IO_H
+//=============================================================================
+//
+// spi_freescale_dspi_io.h
+//
+// IO definitions for Freescale DSPI.
+//
+//=============================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later
+// version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with eCos; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// As a special exception, if other files instantiate templates or use
+// macros or inline functions from this file, or you compile this file
+// and link it with other works to produce a work based on this file,
+// this file does not by itself cause the resulting work to be covered by
+// the GNU General Public License. However the source code for this file
+// must still be made available in accordance with section (3) of the GNU
+// General Public License v2.
+//
+// This exception does not invalidate any other reasons why a work based
+// on this file might be covered by the GNU General Public License.
+// -------------------------------------------
+// ####ECOSGPLCOPYRIGHTEND####
+//=============================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): ilijak
+// Date: 2011-11-03
+// Purpose: Freescale DSPI I/O definitions.
+// Description:
+// Usage: #include <cyg/io/spi_freescale_dspi_io.h>
+//
+//####DESCRIPTIONEND####
+//
+//=============================================================================
+
+
+// ----------------------------------------------------------------------------
+// DSPI
+
+typedef volatile struct cyghwr_devs_freescale_dspi_s {
+ cyg_uint32 mcr; // Module Configuration Register
+ cyg_uint32 reserved_0;
+ cyg_uint32 tcr; // Transfer Count Register
+ // Clock and Transfer Attributes Register
+ cyg_uint32 ctar[CYGHWR_DEVS_SPI_FREESCALE_DSPI_CTAR_NUM];
+#if CYGHWR_DEVS_SPI_FREESCALE_DSPI_CTAR_NUM < 8
+ cyg_uint32 reserved_1[8-CYGHWR_DEVS_SPI_FREESCALE_DSPI_CTAR_NUM];
+#endif
+ cyg_uint32 sr; // Status Register
+ cyg_uint32 rser; // DMA/IRQ Request Select and Enable Register
+ cyg_uint32 pushr; // TX FIFO PUSH Register
+ cyg_uint32 popr; // RX FIFO POP Register
+ // Transmit FIFO Registers
+ cyg_uint32 txfr[CYGHWR_DEVS_SPI_FREESCALE_DSPI_FIFO_SIZE];
+#if CYGHWR_DEVS_SPI_FREESCALE_DSPI_FIFO_SIZE < 16
+ cyg_uint32 reserved_2[16-CYGHWR_DEVS_SPI_FREESCALE_DSPI_FIFO_SIZE];
+#endif
+ // Receive FIFO Registers
+ cyg_uint32 rxfr[CYGHWR_DEVS_SPI_FREESCALE_DSPI_FIFO_SIZE];
+#if CYGHWR_DEVS_SPI_FREESCALE_DSPI_FIFO_SIZE < 16
+ cyg_uint32 reserved_3[16-CYGHWR_DEVS_SPI_FREESCALE_DSPI_FIFO_SIZE];
+#endif
+} cyghwr_devs_freescale_dspi_t;
+
+// MCR Bit Fields
+#define FREESCALE_DSPI_MCR_HALT_M 0x1
+#define FREESCALE_DSPI_MCR_HALT_S 0
+#define FREESCALE_DSPI_MCR_SMPL_PT_M 0x300
+#define FREESCALE_DSPI_MCR_SMPL_PT_S 8
+#define FREESCALE_DSPI_MCR_SMPL_PT(__val) \
+ VALUE_(FREESCALE_DSPI_MCR_SMPL_PT_S, __val)
+#define FREESCALE_DSPI_MCR_CLR_RXF_M 0x400
+#define FREESCALE_DSPI_MCR_CLR_RXF_S 10
+#define FREESCALE_DSPI_MCR_CLR_TXF_M 0x800
+#define FREESCALE_DSPI_MCR_CLR_TXF_S 11
+#define FREESCALE_DSPI_MCR_DIS_RXF_M 0x1000
+#define FREESCALE_DSPI_MCR_DIS_RXF_S 12
+#define FREESCALE_DSPI_MCR_DIS_TXF_M 0x2000
+#define FREESCALE_DSPI_MCR_DIS_TXF_S 13
+#define FREESCALE_DSPI_MCR_MDIS_M 0x4000
+#define FREESCALE_DSPI_MCR_MDIS_S 14
+#define FREESCALE_DSPI_MCR_DOZE_M 0x8000
+#define FREESCALE_DSPI_MCR_DOZE_S 15
+#define FREESCALE_DSPI_MCR_PCSIS_M 0x3F0000
+#define FREESCALE_DSPI_MCR_PCSIS_S 16
+#define FREESCALE_DSPI_MCR_PCSIS(__val) \
+ VALUE_(FREESCALE_DSPI_MCR_PCSIS_S, __val)
+#define FREESCALE_DSPI_MCR_ROOE_M 0x1000000
+#define FREESCALE_DSPI_MCR_ROOE_S 24
+#define FREESCALE_DSPI_MCR_PCSSE_M 0x2000000
+#define FREESCALE_DSPI_MCR_PCSSE_S 25
+#define FREESCALE_DSPI_MCR_MTFE_M 0x4000000
+#define FREESCALE_DSPI_MCR_MTFE_S 26
+#define FREESCALE_DSPI_MCR_FRZ_M 0x8000000
+#define FREESCALE_DSPI_MCR_FRZ_S 27
+#define FREESCALE_DSPI_MCR_DCONF_M 0x30000000
+#define FREESCALE_DSPI_MCR_DCONF_S 28
+#define FREESCALE_DSPI_MCR_DCONF(__val) \
+ VALUE_(FREESCALE_DSPI_MCR_DCONF_S, __val)
+#define FREESCALE_DSPI_MCR_CONT_SCKE_M 0x40000000
+#define FREESCALE_DSPI_MCR_CONT_SCKE_S 30
+#define FREESCALE_DSPI_MCR_MSTR_M 0x80000000
+#define FREESCALE_DSPI_MCR_MSTR_S 31
+// TCR Bit Fields
+#define FREESCALE_DSPI_TCR_DSPI_TCNT_M 0xFFFF0000
+#define FREESCALE_DSPI_TCR_DSPI_TCNT_S 16
+#define FREESCALE_DSPI_TCR_DSPI_TCNT(__val) \
+ VALUE_(FREESCALE_DSPI_TCR_DSPI_TCNT_S, __val)
+// CTAR Bit Fields
+#define FREESCALE_DSPI_CTAR_BR_M 0xF
+#define FREESCALE_DSPI_CTAR_BR_S 0
+#define FREESCALE_DSPI_CTAR_BR(__val) \
+ VALUE_(FREESCALE_DSPI_CTAR_BR_S, __val)
+#define FREESCALE_DSPI_CTAR_DT_M 0xF0
+#define FREESCALE_DSPI_CTAR_DT_S 4
+#define FREESCALE_DSPI_CTAR_DT(__val) \
+ VALUE_(FREESCALE_DSPI_CTAR_DT_S, __val)
+#define FREESCALE_DSPI_CTAR_ASC_M 0xF00
+#define FREESCALE_DSPI_CTAR_ASC_S 8
+#define FREESCALE_DSPI_CTAR_ASC(__val) \
+ VALUE_(FREESCALE_DSPI_CTAR_ASC_S, __val)
+#define FREESCALE_DSPI_CTAR_CSSCK_M 0xF000
+#define FREESCALE_DSPI_CTAR_CSSCK_S 12
+#define FREESCALE_DSPI_CTAR_CSSCK(__val) \
+ VALUE_(FREESCALE_DSPI_CTAR_CSSCK_S, __val)
+#define FREESCALE_DSPI_CTAR_PBR_M 0x30000
+#define FREESCALE_DSPI_CTAR_PBR_S 16
+#define FREESCALE_DSPI_CTAR_PBR(__val) \
+ VALUE_(FREESCALE_DSPI_CTAR_PBR_S, __val)
+#define FREESCALE_DSPI_CTAR_PDT_M 0xC0000
+#define FREESCALE_DSPI_CTAR_PDT_S 18
+#define FREESCALE_DSPI_CTAR_PDT(__val) \
+ VALUE_(FREESCALE_DSPI_CTAR_PDT_S, __val)
+#define FREESCALE_DSPI_CTAR_PASC_M 0x300000
+#define FREESCALE_DSPI_CTAR_PASC_S 20
+#define FREESCALE_DSPI_CTAR_PASC(__val) \
+ VALUE_(FREESCALE_DSPI_CTAR_PASC_S, __val)
+#define FREESCALE_DSPI_CTAR_PCSSCK_S 22
+#define FREESCALE_DSPI_CTAR_PCSSCK(__val) \
+ VALUE_(FREESCALE_DSPI_CTAR_PCSSCK_S, __val)
+#define FREESCALE_DSPI_CTAR_LSBFE_S 24
+#define FREESCALE_DSPI_CTAR_LSBFE_M 0x1000000
+
+#define FREESCALE_DSPI_CTAR_FMSZ_M 0x78000000
+#define FREESCALE_DSPI_CTAR_FMSZ_S 27
+#define FREESCALE_DSPI_CTAR_FMSZ(__val) \
+ VALUE_(FREESCALE_DSPI_CTAR_FMSZ_S, __val)
+#define FREESCALE_DSPI_CTAR_DBR_M 0x80000000
+#define FREESCALE_DSPI_CTAR_DBR_S 31
+// CTAR_SLAVE Bit Fields
+#define FREESCALE_DSPI_CTAR_SLAVE_CPHA_M 0x2000000
+#define FREESCALE_DSPI_CTAR_SLAVE_CPHA_S 25
+#define FREESCALE_DSPI_CTAR_SLAVE_CPOL_M 0x4000000
+#define FREESCALE_DSPI_CTAR_SLAVE_CPOL_S 26
+#define FREESCALE_DSPI_CTAR_SLAVE_FMSZ_M 0xF8000000
+#define FREESCALE_DSPI_CTAR_SLAVE_FMSZ_S 27
+#define FREESCALE_DSPI_CTAR_SLAVE_FMSZ(__val) \
+ VALUE_(FREESCALE_DSPI_CTAR_SLAVE_FMSZ_S, __val)
+// SR Bit Fields
+#define FREESCALE_DSPI_SR_POPNXTPTR_M 0xF
+#define FREESCALE_DSPI_SR_POPNXTPTR_S 0
+#define FREESCALE_DSPI_SR_POPNXTPTR(__val) \
+ VALUE_(FREESCALE_DSPI_SR_POPNXTPTR_S, __val)
+#define FREESCALE_DSPI_SR_RXCTR_M 0xF0
+#define FREESCALE_DSPI_SR_RXCTR_S 4
+#define FREESCALE_DSPI_SR_RXCTR(__val) \
+ VALUE_(FREESCALE_DSPI_SR_RXCTR_S, __val)
+#define FREESCALE_DSPI_SR_TXNXTPTR_M 0xF00
+#define FREESCALE_DSPI_SR_TXNXTPTR_S 8
+#define FREESCALE_DSPI_SR_TXNXTPTR(__val) \
+ VALUE_(FREESCALE_DSPI_SR_TXNXTPTR_S, __val)
+#define FREESCALE_DSPI_SR_TXCTR_M 0xF000
+#define FREESCALE_DSPI_SR_TXCTR_S 12
+#define FREESCALE_DSPI_SR_TXCTR(__val) \
+ VALUE_(FREESCALE_DSPI_SR_TXCTR_S, __val)
+#define FREESCALE_DSPI_SR_RFDF_M 0x20000
+#define FREESCALE_DSPI_SR_RFDF_S 17
+#define FREESCALE_DSPI_SR_RFOF_M 0x80000
+#define FREESCALE_DSPI_SR_RFOF_S 19
+#define FREESCALE_DSPI_SR_TFFF_M 0x2000000
+#define FREESCALE_DSPI_SR_TFFF_S 25
+#define FREESCALE_DSPI_SR_TFUF_M 0x8000000
+#define FREESCALE_DSPI_SR_TFUF_S 27
+#define FREESCALE_DSPI_SR_EOQF_M 0x10000000
+#define FREESCALE_DSPI_SR_EOQF_S 28
+#define FREESCALE_DSPI_SR_TXRXS_M 0x40000000
+#define FREESCALE_DSPI_SR_TXRXS_S 30
+#define FREESCALE_DSPI_SR_TCF_M 0x80000000
+#define FREESCALE_DSPI_SR_TCF_S 31
+
+#define FREESCALE_DSPI_CLEAR_FIFOS (FREESCALE_DSPI_SR_TFUF_M |\
+ FREESCALE_DSPI_SR_RFOF_M)
+
+// RSER Bit Fields
+#define FREESCALE_DSPI_RSER_RFDF_DIRS_M 0x10000
+#define FREESCALE_DSPI_RSER_RFDF_DIRS_S 16
+#define FREESCALE_DSPI_RSER_RFDF_RE_M 0x20000
+#define FREESCALE_DSPI_RSER_RFDF_RE_S 17
+#define FREESCALE_DSPI_RSER_RFOF_RE_M 0x80000
+#define FREESCALE_DSPI_RSER_RFOF_RE_S 19
+#define FREESCALE_DSPI_RSER_TFFF_DIRS_M 0x1000000
+#define FREESCALE_DSPI_RSER_TFFF_DIRS_S 24
+#define FREESCALE_DSPI_RSER_TFFF_RE_M 0x2000000
+#define FREESCALE_DSPI_RSER_TFFF_RE_S 25
+#define FREESCALE_DSPI_RSER_TFUF_RE_M 0x8000000
+#define FREESCALE_DSPI_RSER_TFUF_RE_S 27
+#define FREESCALE_DSPI_RSER_EOQF_RE_M 0x10000000
+#define FREESCALE_DSPI_RSER_EOQF_RE_S 28
+#define FREESCALE_DSPI_RSER_TCF_RE_M 0x80000000
+#define FREESCALE_DSPI_RSER_TCF_RE_S 31
+// PUSHR Bit Fields
+#define FREESCALE_DSPI_PUSHR_TXDATA_M 0xFFFF
+#define FREESCALE_DSPI_PUSHR_TXDATA_S 0
+#define FREESCALE_DSPI_PUSHR_TXDATA(__val) \
+ VALUE_(FREESCALE_DSPI_PUSHR_TXDATA_S, __val)
+#define FREESCALE_DSPI_PUSHR_PCS_M 0x3F0000
+#define FREESCALE_DSPI_PUSHR_PCS_S 16
+#define FREESCALE_DSPI_PUSHR_PCS(__val) VALUE_(FREESCALE_DSPI_PUSHR_PCS_S, __val)
+#define FREESCALE_DSPI_PUSHR_CTCNT_M 0x4000000
+#define FREESCALE_DSPI_PUSHR_CTCNT_S 26
+#define FREESCALE_DSPI_PUSHR_EOQ_M 0x8000000
+#define FREESCALE_DSPI_PUSHR_EOQ_S 27
+#define FREESCALE_DSPI_PUSHR_CTAS_M 0x70000000
+#define FREESCALE_DSPI_PUSHR_CTAS_S 28
+#define FREESCALE_DSPI_PUSHR_CTAS(__val) \
+ VALUE_(FREESCALE_DSPI_PUSHR_CTAS_S, __val)
+#define FREESCALE_DSPI_PUSHR_CONT_M 0x80000000
+#define FREESCALE_DSPI_PUSHR_CONT_S 31
+// PUSHR_SLAVE Bit Fields
+#define FREESCALE_DSPI_PUSHR_SLAVE_TXDATA_M 0xFFFFFFFF
+#define FREESCALE_DSPI_PUSHR_SLAVE_TXDATA_S 0
+#define FREESCALE_DSPI_PUSHR_SLAVE_TXDATA(__val) \
+VALUE_(FREESCALE_DSPI_PUSHR_SLAVE_TXDATA_S, __val)
+
+#define FREESCALE_DSPI_PUSHR_PCS_CLEAR(__val)\
+CYG_MACRO_START\
+ __val &= ~FREESCALE_DSPI_PUSHR_PCS_M; \
+CYG_MACRO_END
+
+// POPR Bit Fields
+#define FREESCALE_DSPI_POPR_RXDATA_M 0xFFFFFFFF
+#define FREESCALE_DSPI_POPR_RXDATA_S 0
+#define FREESCALE_DSPI_POPR_RXDATA(__val) \
+ VALUE_(FREESCALE_DSPI_POPR_RXDATA_S, __val)
+// TXFR Bit Fields
+#define FREESCALE_DSPI_TXFR_TXDATA_M 0xFFFF
+#define FREESCALE_DSPI_TXFR_TXDATA_S 0
+#define FREESCALE_DSPI_TXFR_TXCMD_TXDATA_M 0xFFFF0000
+#define FREESCALE_DSPI_TXFR_TXCMD_TXDATA_S 16
+#define FREESCALE_DSPI_TXFR_TXCMD_TXDATA(__fr,__val) \
+ VALUE_(FREESCALE_DSPI_TXFR##__fr##_TXCMD_TXDATA_S, __val)
+// RXFR Bit Fields
+#define FREESCALE_DSPI_RXFR_RXDATA_M 0xFFFFFFFF
+#define FREESCALE_DSPI_RXFR_RXDATA_S 0
+#define FREESCALE_DSPI_RXFR_RXDATA(__fr,__val) \
+ VALUE_(FREESCALE_DSPI_RXFR##_fr##_RXDATA_S, __val)
+
+// Borrow following macros from HAL
+
+// CYGADDR_IO_SPI_FREESCALE_DSPIx_P
+
+// CYGHWR_IO_CLOCK_ENABLE(__clkgate)
+// CYGHWR_IO_FREESCALE_DSPIx_CLK
+
+// CYGHWR_IO_FREESCALE_DSPI_PIN(__pin)
+
+// CYGHWR_IO_FREESCALE_SPIx_PIN_SIN
+// CYGHWR_IO_FREESCALE_SPIx_PIN_SOUT
+// CYGHWR_IO_FREESCALE_SPIx_PIN_SCK
+
+// CYGHWR_IO_FREESCALE_SPIx_PIN_CSn
+
+//=============================================================================
+#endif // CYGONCE_DEVS_SPI_FREESCALE_DSPI_IO_H
diff --git a/ecos/packages/devs/spi/freescale/dspi/current/src/spi_freescale_dspi.c b/ecos/packages/devs/spi/freescale/dspi/current/src/spi_freescale_dspi.c
new file mode 100644
index 0000000..b6842e1
--- /dev/null
+++ b/ecos/packages/devs/spi/freescale/dspi/current/src/spi_freescale_dspi.c
@@ -0,0 +1,1190 @@
+//=============================================================================
+//
+// spi_freescale_dspi.c
+//
+// SPI driver implementation for Freescale DSPI
+//
+//=============================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2011, 2013 Free Software Foundation, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later
+// version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with eCos; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// As a special exception, if other files instantiate templates or use
+// macros or inline functions from this file, or you compile this file
+// and link it with other works to produce a work based on this file,
+// this file does not by itself cause the resulting work to be covered by
+// the GNU General Public License. However the source code for this file
+// must still be made available in accordance with section (3) of the GNU
+// General Public License v2.
+//
+// This exception does not invalidate any other reasons why a work based
+// on this file might be covered by the GNU General Public License.
+// -------------------------------------------
+// ####ECOSGPLCOPYRIGHTEND####
+//=============================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): ilijak
+// Date: 2011-11-04
+// Purpose: Freescale DSPI SPI driver implementation
+//
+//####DESCRIPTIONEND####
+//
+//=============================================================================
+
+#include <pkgconf/hal.h>
+#include <string.h>
+#include <cyg/hal/hal_io.h>
+#include <cyg/hal/hal_if.h>
+#include <cyg/hal/hal_intr.h>
+#include <cyg/hal/drv_api.h>
+#include <cyg/hal/hal_cache.h>
+
+#include <cyg/infra/cyg_type.h>
+#include <cyg/infra/cyg_ass.h>
+#include <cyg/infra/diag.h>
+
+#include <cyg/io/spi.h>
+#include <cyg/hal/hal_endian.h>
+
+#include <pkgconf/devs_spi_freescale_dspi.h>
+#if defined(CYGHWR_DEVS_SPI_FREESCALE_DSPI0) || \
+ defined(CYGHWR_DEVS_SPI_FREESCALE_DSPI1) || \
+ defined(CYGHWR_DEVS_SPI_FREESCALE_DSPI2)
+
+#include <cyg/io/spi_freescale_dspi.h>
+
+
+#define DEBUG_SPI CYGPKG_DEVS_SPI_FREESCALE_DSPI_DEBUG_LEVEL
+
+#if DEBUG_SPI >= 3
+# define DEBUG3_PRINTF(args...) diag_printf(args)
+#else
+# define DEBUG3_PRINTF(args...)
+#endif
+
+#if DEBUG_SPI >= 2
+# define DEBUG2_PRINTF(args...) diag_printf(args)
+#else
+# define DEBUG2_PRINTF(args...)
+#endif
+
+#if DEBUG_SPI >= 1
+# define DEBUG1_PRINTF(args...) diag_printf(args)
+#else
+# define DEBUG1_PRINTF(args...)
+#endif
+
+# define DEBUG0_PRINTF(args...) diag_printf(args)
+
+#define PUSHR_NULL (0xFFFF)
+
+//-----------------------------------------------------------------------------
+// API function call forward references.
+
+static void dspi_transaction_begin (cyg_spi_device*);
+static void dspi_transaction_transfer (cyg_spi_device*, cyg_bool, cyg_uint32,
+ const cyg_uint8*, cyg_uint8*, cyg_bool);
+static void dspi_transaction_tick (cyg_spi_device*, cyg_bool, cyg_uint32);
+static void dspi_transaction_end (cyg_spi_device*);
+static int dspi_get_config (cyg_spi_device*, cyg_uint32,
+ void*, cyg_uint32*);
+static int dspi_set_config (cyg_spi_device*, cyg_uint32,
+ const void*, cyg_uint32*);
+
+//-----------------------------------------------------------------------------
+// Instantiate the bus state data structures.
+
+#include <cyg/io/spi_freescale_dspi_buses.inl>
+
+// Some hardware manipulation inline functions and macros
+
+static inline void dspi_disable(cyghwr_devs_freescale_dspi_t* dspi_p)
+{
+ dspi_p->mcr |= FREESCALE_DSPI_MCR_MDIS_M;
+}
+
+static inline void dspi_enable(cyghwr_devs_freescale_dspi_t* dspi_p)
+{
+ dspi_p->mcr &= ~FREESCALE_DSPI_MCR_MDIS_M;
+}
+
+static inline void dspi_halt(cyghwr_devs_freescale_dspi_t* dspi_p)
+{
+ dspi_p->mcr |= FREESCALE_DSPI_MCR_HALT_M;
+}
+
+static inline void dspi_tlah(cyghwr_devs_freescale_dspi_t* dspi_p)
+{
+ dspi_p->mcr &= ~FREESCALE_DSPI_MCR_HALT_M;
+}
+
+static inline void
+dspi_irq_enable(cyghwr_devs_freescale_dspi_t* dspi_p, cyg_uint32 irq_mask)
+{
+ dspi_p->rser |= irq_mask;
+}
+
+static inline void
+dspi_irq_disable(cyghwr_devs_freescale_dspi_t* dspi_p, cyg_uint32 irq_mask)
+{
+ dspi_p->rser &= ~irq_mask;
+}
+
+static inline void
+dspi_status_clear(cyghwr_devs_freescale_dspi_t* dspi_p, cyg_uint32 sr_mask)
+{
+ dspi_p->sr |= sr_mask;
+}
+
+static inline void
+dspi_fifo_clear(cyghwr_devs_freescale_dspi_t* dspi_p)
+{
+ dspi_p->mcr |= FREESCALE_DSPI_MCR_CLR_RXF_M | FREESCALE_DSPI_MCR_CLR_TXF_M;
+}
+
+static inline void
+dspi_fifo_drain(cyghwr_devs_freescale_dspi_t* dspi_p)
+{
+ dspi_p->sr |= FREESCALE_DSPI_SR_RFDF_M;
+}
+
+
+#define DSPI_IRQ_ENABLE(__dspi_p) \
+ dspi_irq_enable(__dspi_p, FREESCALE_DSPI_RSER_EOQF_RE_M)
+#define DSPI_IRQ_DISABLE(__dspi_p) \
+ dspi_irq_disable(__dspi_p, FREESCALE_DSPI_RSER_EOQF_RE_M)
+#define DSPI_EOQ_CLEAR(__dspi_p) \
+ dspi_status_clear(__dspi_p, FREESCALE_DSPI_SR_EOQF_M | \
+ FREESCALE_DSPI_SR_TCF_M | \
+ FREESCALE_DSPI_SR_RFDF_M)
+#define DSPI_TXRX_ENABLE(__dspi_p) \
+ dspi_status_clear(__dspi_p, FREESCALE_DSPI_SR_TXRXS_M)
+
+// Alternate clocking for spi_transaction_end()
+// Used to initialize CTAR1.
+static const cyg_freescale_dspi_clocking_t aux_clocking =
+{
+ .frame_size = 4,
+ .cl_pol = 0,
+ .cl_pha = 0,
+ .cl_brate = CYGHWR_DEVS_FREESCALEDSPI_DSPI_CTAR1_AUX_SPEED,
+ .cs_up_udly = CYGHWR_DEVS_FREESCALEDSPI_DSPI_CTAR1_AUX_CS_DELAY,
+ .cs_dw_udly = CYGHWR_DEVS_FREESCALEDSPI_DSPI_CTAR1_AUX_CS_DELAY,
+ .tr_bt_udly =CYGHWR_DEVS_FREESCALEDSPI_DSPI_CTAR1_AUX_CS_DELAY,
+ .dl_unit = CYGNUM_DSPI_DELAY_UNIT(
+ CYGHWR_DEVS_FREESCALE_DSPI_DSPI_CTAR1_AUX_DELAY_UNIT),
+ .cl_dbr = CYGHWR_DEVS_FREESCALEDSPI_DSPI_CTAR1_AUX_USE_DBR
+};
+
+//-----------------------------------------------------------------------------
+// Implement DSPI ISRs.
+
+// ISR for DSPI with DMA
+// Disable DSPI IRQ and Tx DMA channel and schedule DSR.
+static cyg_uint32 dspi_dma_ISR(cyg_vector_t vector, cyg_addrword_t data)
+{
+ cyg_spi_freescale_dspi_bus_t* dspi_bus_p =
+ (cyg_spi_freescale_dspi_bus_t*) data;
+ cyghwr_devs_freescale_dspi_t* dspi_p = dspi_bus_p->setup_p->dspi_p;
+ cyghwr_hal_freescale_dma_set_t *dma_set_p = dspi_bus_p->setup_p->dma_set_p;
+ cyghwr_hal_freescale_edma_t *edma_p;
+ edma_p = dma_set_p->edma_p;
+
+ cyg_drv_isr_lock();
+
+ // Disable the Tx DMA channel and DSPI IRQ.
+ hal_freescale_edma_erq_disable(edma_p, SPI_DMA_CHAN_I(dma_set_p, TX));
+ DSPI_IRQ_DISABLE(dspi_p);
+
+ cyg_drv_interrupt_acknowledge(vector);
+ cyg_drv_isr_unlock();
+ return (CYG_ISR_CALL_DSR | CYG_ISR_HANDLED);
+}
+
+// ISR for DSPI without DMA
+// Disable DSPI IRQ and schedule DSR.
+static cyg_uint32 dspi_nodma_ISR(cyg_vector_t vector, cyg_addrword_t data)
+{
+ cyg_spi_freescale_dspi_bus_t* dspi_bus_p =
+ (cyg_spi_freescale_dspi_bus_t*) data;
+ cyghwr_devs_freescale_dspi_t* dspi_p = dspi_bus_p->setup_p->dspi_p;
+
+ cyg_drv_isr_lock();
+
+ // Disable the DSPI IRQ.
+ DSPI_IRQ_DISABLE(dspi_p);
+
+ cyg_drv_interrupt_acknowledge(vector);
+ cyg_drv_isr_unlock();
+ return (CYG_ISR_CALL_DSR | CYG_ISR_HANDLED);
+}
+
+// DSPI DSR
+static void dspi_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
+{
+ cyg_spi_freescale_dspi_bus_t* dspi_bus = (cyg_spi_freescale_dspi_bus_t*) data;
+
+ cyg_drv_dsr_lock();
+ cyg_drv_cond_signal(&dspi_bus->transfer_done);
+ cyg_drv_dsr_unlock();
+}
+
+//-----------------------------------------------------------------------------
+// Calculate best fit CTAR baud rate setting (using some brute force).
+// Best fit is considered the highest frequency that is not highe than set point.
+
+static const cyg_uint16 ctar_br[16] = { 2/2, 4/2, 6/2, 8/2, 16/2, 32/2, 64/2,
+ 128/2, 256/2, 512/2, 1024/2, 2048/2, 4096/2, 8192/2, 16384/2, 32768/2 };
+static const cyg_uint8 ctar_pbr[4] = { 2, 3, 5, 7 };
+
+static const cyg_uint16 ctar_cssck[16] = { 2/2, 4/2, 8/2, 16/2, 32/2, 64/2,
+ 128/2, 256/2, 512/2, 1024/2, 2048/2, 4096/2, 8192/2, 16384/2, 32768/2,
+ 65536/2 };
+static const cyg_uint8 ctar_pcssck[4] = { 1, 3, 5, 7 };
+
+typedef struct ctar_br_s {
+ cyg_uint8 valid;
+ cyg_uint8 br;
+ cyg_uint8 dbr;
+ cyg_uint8 pbr;
+} ctar_br_t;
+
+static int dspi_ctar_brbf (const cyg_freescale_dspi_clocking_t* spi_cocking,
+ ctar_br_t* brs_p, const cyg_uint16* br_p,
+ const cyg_uint8* pbr_p, cyg_uint32* alt_brate,
+ cyg_uint32 sys_clk)
+{
+ cyg_uint32 pbr_i;
+ cyg_uint32 br_i;
+ cyg_uint32 dbr;
+ cyg_uint32 clk;
+ cyg_uint32 baud_bf = 0; // Best fit
+ cyg_uint32 baud_tmp;
+ cyg_uint32 baud_sp = alt_brate ? *alt_brate :
+ spi_cocking->cl_brate; // Set point
+
+ // Calculate the maximal viable bus speed.
+ clk = sys_clk;
+ // Desired baud rate very high, use DBR if allowed
+ dbr = (baud_sp > (clk / 4)) && spi_cocking->cl_dbr && (br_p == ctar_br);
+
+ for(pbr_i = 0; pbr_i < 3; pbr_i++) {
+ for(br_i = 0; br_i < 15; br_i++) {
+ if((baud_tmp = (clk * (1+dbr)) / (pbr_p[pbr_i] * (2*br_p[br_i])))
+ <= baud_sp)
+ {
+ if(baud_tmp > baud_bf) {
+ DEBUG3_PRINTF("DSPI Baud:"
+ " SP=%d pbr=0x%x br=0x%x dbr=%d Temp=%d (SysClk=%d)\n",
+ baud_sp, pbr_i, br_i, dbr, baud_tmp, clk);
+ brs_p->br = br_i;
+ brs_p->pbr = pbr_i;
+ brs_p->valid = 1;
+ baud_bf = baud_tmp;
+ if(baud_tmp == baud_sp)
+ goto baud_found;
+ }
+ }
+ }
+ }
+ if(!brs_p->valid) {
+ pbr_i = 3;
+ br_i = 15;
+ DEBUG1_PRINTF("DSPI Baud too low:"
+ " SP=%d pbr=0x%x br=0x%x Actual=%d (SysClk=%d)\n",
+ baud_sp, pbr_i, br_i,
+ (clk * (1+dbr)) / (pbr_p[pbr_i] * (2*br_p[br_i])), clk);
+ brs_p->br = br_i;
+ brs_p->pbr = pbr_i;
+
+ return -1;
+ } else {
+baud_found:
+ brs_p->dbr = dbr;
+ DEBUG1_PRINTF("DSPI Baud found:"
+ " SP=%d pbr=0x%x br=0x%x dbr=%d Actual=%dHz (%dns) (SysClk=%d)\n",
+ baud_sp, brs_p->pbr, brs_p->br, dbr, baud_bf, 1000000000/baud_bf, clk);
+
+ return 0;
+ }
+}
+
+// Set Clock and Transfer Attributes Register
+#define CYG_ASSERT_LOW_FREQ \
+ CYG_ASSERT (false, "Freescale DSPI: Cannot run bus as slowly as requested.")
+cyg_uint32
+dspi_calc_ctar(const cyg_freescale_dspi_clocking_t* spi_clocking, cyg_uint32 sys_clk)
+{
+ cyg_uint32 regval;
+ ctar_br_t brs;
+ cyg_uint32 delay_brate;
+
+ regval = FREESCALE_DSPI_CTAR_FMSZ(spi_clocking->frame_size - 1);
+ if(spi_clocking->cl_pol)
+ regval |= FREESCALE_DSPI_CTAR_SLAVE_CPOL_M;
+ if(spi_clocking->cl_pha)
+ regval |= FREESCALE_DSPI_CTAR_SLAVE_CPHA_M;
+ if(spi_clocking->lsb_first)
+ regval |= FREESCALE_DSPI_CTAR_LSBFE_M;
+
+ // Get divider bits
+ // Baud rate
+ brs.dbr = 0;
+ if (!dspi_ctar_brbf(spi_clocking, &brs, ctar_br, ctar_pbr, NULL, sys_clk))
+ {
+ regval |= FREESCALE_DSPI_CTAR_BR(brs.br) |
+ FREESCALE_DSPI_CTAR_PBR(brs.pbr) |
+ (brs.dbr ? FREESCALE_DSPI_CTAR_DBR_M : 0);
+ } else
+ CYG_ASSERT_LOW_FREQ;
+
+ delay_brate = 100000000 / (spi_clocking->dl_unit * spi_clocking->cs_up_udly);
+ if (!dspi_ctar_brbf(spi_clocking, &brs, ctar_cssck, ctar_pcssck,
+ &delay_brate, sys_clk))
+ {
+ regval |= FREESCALE_DSPI_CTAR_CSSCK(brs.br) |
+ FREESCALE_DSPI_CTAR_PCSSCK(brs.pbr);
+ } else
+ CYG_ASSERT_LOW_FREQ;
+
+ // Delay between clock and CS negation
+ delay_brate = 100000000 / (spi_clocking->dl_unit * spi_clocking->cs_dw_udly);
+ if (!dspi_ctar_brbf(spi_clocking, &brs, ctar_cssck, ctar_pcssck,
+ &delay_brate, sys_clk))
+ {
+ regval |= FREESCALE_DSPI_CTAR_ASC(brs.br) |
+ FREESCALE_DSPI_CTAR_PASC(brs.pbr);
+ } else
+ CYG_ASSERT_LOW_FREQ;
+
+ // Delay between clock and CS negation and assertion
+ delay_brate = 100000000 / (spi_clocking->dl_unit * spi_clocking->tr_bt_udly);
+ if (!dspi_ctar_brbf(spi_clocking, &brs, ctar_cssck, ctar_pcssck,
+ &delay_brate, sys_clk))
+ {
+ regval |= FREESCALE_DSPI_CTAR_DT(brs.br) |
+ FREESCALE_DSPI_CTAR_PDT(brs.pbr);
+ } else
+ CYG_ASSERT_LOW_FREQ;
+ return regval;
+}
+
+//----------------------------------------------------------------------------
+//Set up SPI bus pins
+
+static void dspi_pin_setup(const cyg_uint32* spi_pins_p,
+ const cyg_uint32* cs_pins_p, cyg_uint32 cs_pin_n)
+{
+ const cyg_uint32* pin_p;
+
+ for(pin_p = spi_pins_p;
+ pin_p < spi_pins_p + 3;
+ CYGHWR_IO_FREESCALE_DSPI_PIN(*pin_p++));
+
+ for(pin_p = cs_pins_p;
+ pin_p < cs_pins_p + cs_pin_n;
+ CYGHWR_IO_FREESCALE_DSPI_PIN(*pin_p++));
+}
+
+//-----------------------------------------------------------------------------
+// Set up a new SPI bus on initialisation.
+
+static void dspi_bus_setup(cyg_spi_freescale_dspi_bus_t* spi_bus_p)
+{
+ cyghwr_devs_freescale_dspi_t* dspi_p = spi_bus_p->setup_p->dspi_p;
+ cyghwr_hal_freescale_dma_set_t* dma_set_p;
+ cyghwr_hal_freescale_edma_t* edma_p;
+ cyg_uint32 dma_chan_i;
+
+ // Set up the clocking.
+ CYGHWR_IO_CLOCK_ENABLE(spi_bus_p->setup_p->clk_gate);
+ spi_bus_p->clock_freq = CYGHWR_IO_SPI_FREESCALE_DSPI_CLOCK;
+ DEBUG1_PRINTF("DSPI BUS %p: SysClk=%d\n", spi_bus_p, spi_bus_p->clock_freq);
+
+ // Set up the pins.
+ dspi_pin_setup(spi_bus_p->setup_p->spi_pin_list_p,
+ spi_bus_p->setup_p->cs_pin_list_p,
+ spi_bus_p->setup_p->cs_pin_num);
+
+ // Set up default SPI configuration.
+ dspi_p->mcr = spi_bus_p->setup_p->mcr_opt | FREESCALE_DSPI_MCR_MSTR_M |
+ FREESCALE_DSPI_MCR_CLR_RXF_M | FREESCALE_DSPI_MCR_CLR_TXF_M |
+ FREESCALE_DSPI_MCR_MDIS_M;
+
+ // Enable DSPI controller.
+ dspi_enable(dspi_p);
+
+ if((dma_set_p=spi_bus_p->setup_p->dma_set_p)) {
+ // Initialize DMA channels
+ hal_freescale_edma_init_chanset(dma_set_p);
+#if DEBUG_SPI >= 1
+ hal_freescale_edma_diag(dma_set_p, 0xffff);
+ cyghwr_devs_freescale_dspi_diag(spi_bus_p);
+#endif
+ // Set up DMA transfer control descriptors
+ edma_p = dma_set_p->edma_p;
+ dma_chan_i = dma_set_p->chan_p[SPI_DMA_CHAN_TX_I].dma_chan_i;
+ hal_freescale_edma_transfer_init(edma_p, dma_chan_i,
+ spi_bus_p->tx_dma_tcd_ini_p);
+#if DEBUG_SPI >= 1
+ hal_freescale_edma_transfer_diag(edma_p, dma_chan_i, true);
+#endif
+ dma_chan_i = dma_set_p->chan_p[SPI_DMA_CHAN_RX_I].dma_chan_i;
+ hal_freescale_edma_transfer_init(edma_p, dma_chan_i,
+ spi_bus_p->rx_dma_tcd_ini_p);
+#if DEBUG_SPI >= 1
+ hal_freescale_edma_transfer_diag(edma_p, dma_chan_i, true);
+#endif
+ }
+#if DEBUG_SPI >= 1
+ cyghwr_devs_freescale_dspi_diag(spi_bus_p);
+#endif
+ // Initialise the synchronisation primitivies.
+ cyg_drv_mutex_init (&spi_bus_p->transfer_mutex);
+ cyg_drv_cond_init (&spi_bus_p->transfer_done, &spi_bus_p->transfer_mutex);
+
+ // Hook up the ISR and DSR.
+ cyg_drv_interrupt_create (spi_bus_p->setup_p->intr_num,
+ spi_bus_p->setup_p->intr_prio,
+ (cyg_addrword_t) spi_bus_p,
+ dma_set_p ? dspi_dma_ISR : dspi_nodma_ISR,
+ dspi_DSR, &spi_bus_p->intr_handle,
+ &spi_bus_p->intr_data);
+ cyg_drv_interrupt_attach (spi_bus_p->intr_handle);
+
+ dspi_p->ctar[1] = dspi_calc_ctar(&aux_clocking, spi_bus_p->clock_freq);
+
+ // Call upper layer bus init.
+ CYG_SPI_BUS_COMMON_INIT(&spi_bus_p->spi_bus);
+}
+
+//-----------------------------------------------------------------------------
+// Set up Rx DMA channel
+static void
+rx_dma_channel_setup(cyghwr_hal_freescale_dma_set_t *dma_set_p,
+ cyg_uint8* data_buf, cyg_uint32 bus_16bit,
+ volatile cyghwr_hal_freescale_edma_tcd_t *tcd_p)
+{
+ cyg_uint32 step, sdsize;
+ static cyg_uint8 popr_sink;
+
+ // Set the correct transfer size.
+ if(bus_16bit) {
+ step = 2;
+ sdsize = FREESCALE_EDMA_ATTR_SIZE_16;
+ } else {
+ step = 1;
+ sdsize = FREESCALE_EDMA_ATTR_SIZE_8;
+ }
+ if(data_buf) {
+ tcd_p->doff = step;
+ tcd_p->daddr = data_buf;
+ } else {
+ tcd_p->doff = 0;
+ tcd_p->daddr = &popr_sink;
+ }
+ tcd_p->nbytes.mlno = step;
+ tcd_p->attr = FREESCALE_EDMA_ATTR_SSIZE(sdsize) |
+ FREESCALE_EDMA_ATTR_DSIZE(sdsize) |
+ FREESCALE_EDMA_ATTR_SMOD(0) |
+ FREESCALE_EDMA_ATTR_DMOD(0);
+#if DEBUG_SPI >= 3
+ hal_freescale_edma_tcd_diag(tcd_p, -1, "[DSPI Rx]");
+#endif
+}
+
+//----------------------------------------------------------------------------
+// Set up Tx FIFO queue
+// Set up Tx FIFO command queue
+// DSPI requires sending command for every transfer.
+// Used for transfers that fit within DSPI FIFO.
+
+#if DEBUG_SPI >= 2
+static const char debug_format[] = "BUFF %dbit %s: %p 0x%08x remain %d:\n";
+static const char debug_format1[] = "PUSHR 0x%08x %s: %p 0x%08x remain %d:\n";
+#endif
+
+static inline volatile cyg_uint32
+fifo_pushque_fill(cyg_spi_freescale_dspi_bus_t* dspi_bus, cyg_uint8*
+ data_p, cyg_uint32 count, cyg_bool bus_16bit, cyg_uint32 pushr,
+ cyg_bool drop_cs)
+{
+ cyghwr_devs_freescale_dspi_t* dspi_p = dspi_bus->setup_p->dspi_p;
+ cyg_uint32 txfifo_n = dspi_bus->txfifo_n;
+
+ if(data_p) {
+ if(!bus_16bit) {
+ for(; count > 1; count--) {
+ if(!(--txfifo_n)) {
+ dspi_p->pushr = pushr |= *data_p | FREESCALE_DSPI_PUSHR_EOQ_M;
+ count--;
+ DEBUG2_PRINTF(debug_format, 8, "FBK", data_p,
+ pushr | *data_p, count);
+ return count;
+ }
+ DEBUG3_PRINTF(debug_format, 8, "FAD", data_p,
+ pushr | *data_p, count-1);
+ dspi_p->pushr = pushr | *data_p++;
+ }
+ pushr |= *data_p;
+ } else {
+ cyg_uint16* data16_p = (cyg_uint16 *)data_p;
+ cyg_uint16 data_word;
+
+ for(; count > 2; count-=2) {
+ if(!(--txfifo_n)) {
+ dspi_p->pushr = pushr |= *data16_p | FREESCALE_DSPI_PUSHR_EOQ_M;
+ count-=2;
+ DEBUG2_PRINTF(debug_format, 16, "FBK", data_p,
+ pushr, count);
+ return count;
+ }
+ DEBUG3_PRINTF(debug_format, 16, "FAD", data16_p,
+ pushr | *data16_p, (count-1)*2);
+ data_word = *data16_p++;
+ dspi_p->pushr = pushr | data_word;
+ }
+ data_word = *data16_p;
+ pushr |= data_word;
+ }
+ } else {
+ pushr |= PUSHR_NULL;
+ for(; count > 1; count--) {
+ if(!(--txfifo_n)) {
+ dspi_p->pushr = pushr |= FREESCALE_DSPI_PUSHR_EOQ_M;
+ count--;
+ DEBUG2_PRINTF(debug_format, 0, "FBK", &dspi_p->pushr,
+ pushr, count);
+ return count;
+ }
+ dspi_p->pushr = pushr;
+ DEBUG3_PRINTF(debug_format, 0, "FAD", &dspi_p->pushr, pushr,
+ count-1);
+ }
+ }
+ if(drop_cs)
+ pushr &= ~FREESCALE_DSPI_PUSHR_CONT_M;
+ dspi_p->pushr = pushr |= FREESCALE_DSPI_PUSHR_EOQ_M;
+ DEBUG2_PRINTF(data_p ? debug_format : debug_format1, data_p ? (bus_16bit ? 16 :8) : pushr,
+ (drop_cs ? "FEN" : "FSG"), data_p /*&dspi_p->pushr*/, pushr, 0);
+ return 0;
+}
+
+//----------------------------------------------------------------------------
+// Set up Tx
+// Set up Tx DMA command queue
+// DSPI requires sending command for every transfer.
+// Used for transfers larger than DSPI FIFO
+
+static inline volatile cyg_uint32
+dma_pushque_fill(cyg_spi_freescale_dspi_bus_t* dspi_bus, cyg_uint8* data_p,
+ cyg_uint32 count, cyg_bool bus_16bit, cyg_uint32 pushr,
+ cyg_bool drop_cs)
+{
+ volatile cyg_uint32* pushque_p;
+ volatile cyg_uint32* pushque_end;
+
+ pushque_p = dspi_bus->pushque_p;
+ pushque_end = pushque_p + (dspi_bus->pushque_n - (bus_16bit ? 2 : 1));
+ pushque_p = dspi_bus->pushque_p;
+ if(data_p) {
+ if(!bus_16bit) {
+ do {
+ if(pushque_p == pushque_end) {
+ *pushque_p = pushr | *data_p | FREESCALE_DSPI_PUSHR_EOQ_M;
+ count--;
+
+ DEBUG2_PRINTF(debug_format, 8, "BRK", pushque_p,
+ pushque_p[0], count);
+ return count;
+ }
+ *pushque_p++ = pushr | *data_p++;
+ DEBUG3_PRINTF(debug_format, 8, "ADD", pushque_p-1,
+ pushque_p[-1], count-1);
+ } while(--count > 1);
+ pushr |= *data_p;
+ } else {
+ cyg_uint16* data16_p = (cyg_uint16 *)data_p;
+ cyg_uint16 data_word;
+ do {
+ if(pushque_p == pushque_end) {
+ data_word = *data16_p;
+ *pushque_p = pushr | data_word | FREESCALE_DSPI_PUSHR_EOQ_M;
+ count-=2;
+
+ DEBUG2_PRINTF(debug_format, 16, "BRK", pushque_p,
+ pushque_p[0], count);
+ return count;
+ }
+ data_word = *data16_p++;
+ *pushque_p++ = pushr | data_word;
+ DEBUG3_PRINTF(debug_format, 16, "ADD", pushque_p-1,
+ pushque_p[-1], count-2);
+ } while((count -= 2) > 2);
+ data_word = *data16_p;
+ pushr |= data_word;
+ }
+ } else {
+ pushr |= PUSHR_NULL;
+ do {
+ if(pushque_p == pushque_end) {
+ *pushque_p = pushr | FREESCALE_DSPI_PUSHR_EOQ_M;
+ count--;
+
+ DEBUG2_PRINTF(debug_format, 0, "BRK", pushque_p,
+ pushque_p[0], count);
+ return count;
+ }
+ *pushque_p++ = pushr;
+ DEBUG3_PRINTF(debug_format, 0, "ADD", pushque_p-1, pushque_p[-1],
+ count-1);
+ } while(--count > 1);
+ }
+ if(drop_cs) pushr &= ~FREESCALE_DSPI_PUSHR_CONT_M;
+ *pushque_p = pushr |= FREESCALE_DSPI_PUSHR_EOQ_M;
+ DEBUG2_PRINTF(debug_format, data_p ? (bus_16bit ? 16 :8) : 0,
+ (drop_cs ? "END" : "SGM"), pushque_p, pushque_p[0], 0);
+
+ return 0;
+}
+
+// Set up Tx DMA channel
+// Used for transfers larger than DSPI FIFO
+
+static inline cyg_uint32
+tx_dma_channel_setup(cyg_spi_freescale_dspi_bus_t* dspi_bus,
+ cyg_uint8* data_buf, cyg_uint32 count,
+ cyg_bool bus_16bit,
+ cyg_uint32 pushr, cyg_bool drop_cs)
+{
+ cyghwr_hal_freescale_dma_set_t *dma_set_p = dspi_bus->setup_p->dma_set_p;
+ cyghwr_hal_freescale_edma_t *edma_p = dma_set_p->edma_p;
+ volatile cyghwr_hal_freescale_edma_tcd_t *tcd_p;
+ cyg_uint32 remain=0;
+ cyg_uint32 dma_chan_i;
+
+ remain = dma_pushque_fill(dspi_bus, data_buf, count, bus_16bit, pushr, drop_cs);
+ dma_chan_i = SPI_DMA_CHAN_I(dma_set_p, TX);
+ tcd_p = &edma_p->tcd[dma_chan_i];
+ tcd_p->saddr = dspi_bus->pushque_p;
+ DEBUG2_PRINTF("DSPI: Tx channel setup\n");
+#if DEBUG_SPI >= 3
+ hal_freescale_edma_transfer_diag(edma_p, dma_chan_i, true);
+#endif
+ return remain;
+}
+
+//-----------------------------------------------------------------------------
+// Set SPI peripheral chip select.
+
+static inline cyg_uint32
+dspi_chip_select_set(cyg_int32 cs_i, cyg_bool pccse, cyg_bool assert)
+{
+ cyg_uint32 spi_pushr;
+
+ if(cs_i < 0) {
+ spi_pushr = 0;
+ } else {
+ if(pccse) {
+ spi_pushr = cs_i;
+ } else {
+ if(cs_i < 5) {
+ if(assert) {
+ cs_i = 1 << cs_i;
+ spi_pushr = FREESCALE_DSPI_PUSHR_PCS(cs_i);
+ } else
+ spi_pushr = 0;
+ } else {
+ CYG_ASSERT(1, "DSPI: Peripheral Chip Select out of range.\n");
+ spi_pushr = 1 << 5;
+ }
+ }
+ }
+ return spi_pushr;
+}
+
+//-----------------------------------------------------------------------------
+// Execute SPI transaction.
+
+static void spi_transaction_do (cyg_spi_device* device, cyg_bool tick_only,
+ cyg_bool polled, cyg_uint32 count,
+ const cyg_uint8* tx_data, cyg_uint8* rx_data,
+ cyg_bool drop_cs)
+{
+ cyg_spi_freescale_dspi_bus_t* dspi_bus =
+ (cyg_spi_freescale_dspi_bus_t*) device->spi_bus;
+ cyg_spi_freescale_dspi_device_t* dspi_device =
+ (cyg_spi_freescale_dspi_device_t*) device;
+ cyg_bool bus_16bit = dspi_device->clocking.bus_16bit;
+ cyghwr_devs_freescale_dspi_t* dspi_p = dspi_bus->setup_p->dspi_p;
+
+ cyghwr_hal_freescale_dma_set_t* dma_set_p;
+ cyghwr_hal_freescale_edma_t* edma_p = NULL;
+
+ cyg_uint32 count_down;
+ cyg_uint32 txfifo_n = dspi_bus->txfifo_n;
+ cyg_uint32 pushr;
+ cyg_uint32 pushque_n;
+ cyg_uint32 dma_chan_rx_i = 0;
+ cyg_uint32 dma_chan_tx_i = 0;
+ cyg_uint8* rx_data0;
+
+#if DEBUG_SPI >= 2
+ cyg_uint32 first_turn = 1;
+#endif
+
+ DEBUG2_PRINTF("DSPI: transaction: count=%d drop_cs=%d tick_only=%d\n",
+ count, drop_cs, tick_only);
+
+ // Set up peripheral CS field. DSPI automatically asserts and deasserts CS
+ pushr =
+#ifndef CYGOPT_DEVS_SPI_FREESCALE_DSPI_TICK_ONLY_DROPS_CS
+ // Compatibility option
+ // eCos Reference Manual states that CS should drop prior to sending
+ // ticks, but other SPI drivers do not touch the CS.
+ tick_only ? dspi_p->pushr & 0x87FF0000 :
+#endif
+ dspi_chip_select_set(
+#ifdef CYGOPT_DEVS_SPI_FREESCALE_DSPI_TICK_ONLY_DROPS_CS
+ // Compatibility option. See comment above.
+ tick_only ? -1 :
+#endif
+ dspi_device->dev_num,
+ dspi_p->mcr & FREESCALE_DSPI_MCR_PCSSE_M, true);
+ pushr |= FREESCALE_DSPI_PUSHR_CONT_M;
+
+ dspi_fifo_clear(dspi_p);
+
+ pushque_n = dspi_bus->pushque_n;
+ if(bus_16bit)
+ txfifo_n *= 2;
+
+ dma_set_p = dspi_bus->setup_p->dma_set_p;
+ if((count > txfifo_n) && dma_set_p) {
+ rx_data0 = rx_data;
+ edma_p = dma_set_p->edma_p;
+ // Set up the DMA channels.
+ dma_chan_rx_i = SPI_DMA_CHAN_I(dma_set_p, RX);
+ dma_chan_tx_i = SPI_DMA_CHAN_I(dma_set_p, TX);
+ rx_dma_channel_setup(dma_set_p, (cyg_uint8*) rx_data,
+ bus_16bit, &edma_p->tcd[dma_chan_rx_i]);
+ hal_freescale_edma_erq_enable(edma_p, dma_chan_rx_i);
+ dspi_irq_enable(dspi_p,
+ FREESCALE_DSPI_RSER_TFFF_RE_M |
+ FREESCALE_DSPI_RSER_RFDF_RE_M |
+ FREESCALE_DSPI_RSER_TFFF_DIRS_M |
+ FREESCALE_DSPI_RSER_RFDF_DIRS_M);
+ } else {
+ rx_data0 = NULL;
+ // If byte count fits in the FIFO don't bother with DMA.
+ if(dma_set_p) {
+ edma_p = dma_set_p->edma_p;
+ hal_freescale_edma_erq_disable(edma_p, SPI_DMA_CHAN_I(dma_set_p, RX));
+ }
+ dma_set_p = NULL;
+ dspi_irq_disable(dspi_p,
+ FREESCALE_DSPI_RSER_TFFF_RE_M |
+ FREESCALE_DSPI_RSER_RFDF_RE_M |
+ FREESCALE_DSPI_RSER_TFFF_DIRS_M |
+ FREESCALE_DSPI_RSER_RFDF_DIRS_M);
+ }
+
+ if(!polled)
+ cyg_drv_interrupt_unmask(dspi_bus->setup_p->intr_num);
+ count_down = count;
+ while(count_down) {
+#if DEBUG_SPI >= 2
+ if(first_turn) {
+ if(dspi_bus->pushque_p)
+ dspi_bus->pushque_p[0] |= FREESCALE_DSPI_PUSHR_CTCNT_M;
+ first_turn = 0;
+ }
+#endif
+ if(dma_set_p && (count_down > txfifo_n)) {
+ // Transfer size is larger than DSPI FIFO
+ // Use DMA Tx
+ count_down = tx_dma_channel_setup(dspi_bus, (cyg_uint8*) tx_data,
+ count_down, bus_16bit,
+ pushr, drop_cs);
+#if DEBUG_SPI >= 3
+ hal_freescale_edma_transfer_diag(edma_p, dma_chan_rx_i, true);
+#endif
+ // Enable the Tx DMA / SPI controller.
+ hal_freescale_edma_erq_enable(edma_p, dma_chan_tx_i);
+ DSPI_EOQ_CLEAR(dspi_p);
+ } else {
+ // Transfer size fits within DSPI FIFO
+ // No need for DMA Tx
+ DSPI_EOQ_CLEAR(dspi_p);
+ count_down = fifo_pushque_fill(dspi_bus, (cyg_uint8*) tx_data,
+ count_down, bus_16bit,
+ pushr, drop_cs);
+#if DEBUG_SPI >= 3
+ cyghwr_devs_freescale_dspi_diag(dspi_bus);
+#endif
+ }
+
+ if(polled) {
+ DEBUG2_PRINTF("DSPI Polled:\n");
+ // Busy-wait for DSPI/DMA (polling for completion).
+ while(!(dspi_p->sr & FREESCALE_DSPI_SR_EOQF_M));
+
+ if(dma_set_p) {
+ // Disable the Tx DMA channel on completion.
+ hal_freescale_edma_erq_disable(edma_p, dma_chan_tx_i);
+ }
+ } else {
+ // Wait for DSPI/DMA completion. (interrupt driven).
+ cyg_drv_mutex_lock(&dspi_bus->transfer_mutex);
+ cyg_drv_dsr_lock();
+
+ DSPI_IRQ_ENABLE(dspi_p);
+ DEBUG2_PRINTF("DSPI IRQ: Enabled\n");
+
+ // Sit back and wait for the ISR/DSRs to signal completion.
+ cyg_drv_cond_wait (&dspi_bus->transfer_done);
+
+ cyg_drv_dsr_unlock();
+ cyg_drv_mutex_unlock(&dspi_bus->transfer_mutex);
+ }
+
+ if(dma_set_p) {
+ // Make sure that Rx has been drained by DMA.
+ while((dspi_p->sr & FREESCALE_DSPI_SR_RFDF_M));
+ DEBUG2_PRINTF("Fifo Drained by DMA 0x%08x\n", dspi_p->sr);
+ if(count_down <= txfifo_n && count_down > 0) {
+ hal_freescale_edma_erq_disable(edma_p, dma_chan_rx_i);
+ dma_set_p = NULL;
+ }
+ } else {
+ // No DMA - "manually" drain Rx FIFO
+ DEBUG2_PRINTF("DSPI FIFO: 'Manually' drain Rx fifo rx_data=%p bus_16bit=%d\n",
+ rx_data, bus_16bit);
+#if DEBUG_SPI >= 3
+ cyghwr_devs_freescale_dspi_diag(dspi_bus);
+#endif
+ if(rx_data) {
+ if(bus_16bit) {
+ cyg_uint16* rx_data16 = (cyg_uint16*) rx_data;
+ while(dspi_p->sr & FREESCALE_DSPI_SR_RXCTR_M) {
+ DEBUG2_PRINTF(" Fifo Pull16 at %p\n", rx_data16);
+ *rx_data16++ = dspi_p->popr;
+ }
+ rx_data = (cyg_uint8*) rx_data16;
+ } else {
+ while(dspi_p->sr & FREESCALE_DSPI_SR_RXCTR_M) {
+ DEBUG2_PRINTF(" Fifo Pull at %p\n", rx_data);
+ *rx_data++ = dspi_p->popr;
+ }
+ }
+ }
+ dspi_fifo_drain(dspi_p);
+ }
+ dspi_fifo_clear(dspi_p);
+ // Prepare for next iteration
+ if(tx_data) {
+ tx_data += pushque_n;
+ if(bus_16bit)
+ tx_data += pushque_n;
+ }
+ }
+ if(rx_data0) {
+ // Rx buffer may be out of sync with cache.
+ DEBUG2_PRINTF("DSPI DMA: Flush cache %p len=%d\n", rx_data0, count);
+ HAL_DCACHE_INVALIDATE(rx_data0, count);
+ DEBUG2_PRINTF("DSPI DMA: Cache flushed\n");
+ }
+
+ if(!polled)
+ cyg_drv_interrupt_mask(dspi_bus->setup_p->intr_num);
+
+ dspi_device->chip_sel = !drop_cs;
+ DEBUG2_PRINTF("cyg_transaction_do() chip_sel = %d drop_cs = %d\n", dspi_device->chip_sel, drop_cs);
+}
+
+//-----------------------------------------------------------------------------
+// Initialise SPI interfaces on startup.
+
+static void CYGBLD_ATTRIB_C_INIT_PRI(CYG_INIT_BUS_SPI)
+dspi_spi_init(void)
+{
+#ifdef CYGHWR_DEVS_SPI_FREESCALE_DSPI0
+ dspi_bus_setup (&cyg_spi_dspi_bus0);
+#endif
+
+#ifdef CYGHWR_DEVS_SPI_FREESCALE_DSPI1
+ dspi_bus_setup (&cyg_spi_dspi_bus1);
+#endif
+
+#ifdef CYGHWR_DEVS_SPI_FREESCALE_DSPI2
+ dspi_bus_setup (&cyg_spi_dspi_bus2);
+#endif
+}
+
+
+//-----------------------------------------------------------------------------
+// Start a SPI transaction.
+
+static void dspi_transaction_begin(cyg_spi_device* device)
+{
+ cyg_spi_freescale_dspi_bus_t* dspi_bus =
+ (cyg_spi_freescale_dspi_bus_t*) device->spi_bus;
+ cyg_spi_freescale_dspi_device_t* dspi_device =
+ (cyg_spi_freescale_dspi_device_t*) device;
+
+ // On the first transaction, generate the values to be programmed into the
+ // SPI configuration registers for this device and cache them. This avoids
+ // having to recalculate the prescaler for every transaction.
+ if(!(dspi_device->clocking.dspi_ctar))
+ dspi_device->clocking.dspi_ctar = dspi_calc_ctar(&dspi_device->clocking,
+ dspi_bus->clock_freq);
+ // Set up the SPI controller.
+ dspi_bus->setup_p->dspi_p->ctar[0] = dspi_device->clocking.dspi_ctar;
+#if DEBUG_SPI >= 2
+ cyghwr_devs_freescale_dspi_diag(dspi_bus);
+#endif
+}
+
+//-----------------------------------------------------------------------------
+// Run a transaction transfer.
+
+static void dspi_transaction_transfer(cyg_spi_device* device, cyg_bool polled,
+ cyg_uint32 count,
+ const cyg_uint8* tx_data,
+ cyg_uint8* rx_data,
+ cyg_bool drop_cs)
+{
+ cyg_spi_freescale_dspi_device_t* dspi_device =
+ (cyg_spi_freescale_dspi_device_t*) device;
+
+ DEBUG2_PRINTF("Transaction rx_data = %p tx_data = %p count=%d\n", rx_data, tx_data, count);
+
+ // Check for unsupported transactions.
+ CYG_ASSERT (count > 0, "DSPI: Null transfer requested.");
+
+ // We check that the buffers are half-word aligned and that count is a
+ // multiple of two in order to carry out the 16-bit transfer.
+ if (dspi_device->clocking.bus_16bit) {
+ CYG_ASSERT (!(count & 1) && !((cyg_uint32) tx_data & 1) &&
+ !((cyg_uint32) rx_data & 1),
+ "DSPI: Misaligned data in 16-bit transfer.");
+ }
+ spi_transaction_do (device, false, polled, count, tx_data, rx_data, drop_cs);
+}
+
+//-----------------------------------------------------------------------------
+// Carry out a bus tick operation - this drops chip select then pushes the
+// required number of NULL frames onto the bus.
+
+static void dspi_transaction_tick(cyg_spi_device* device, cyg_bool polled,
+ cyg_uint32 count)
+{
+ cyg_spi_freescale_dspi_device_t* dspi_device =
+ (cyg_spi_freescale_dspi_device_t*) device;
+
+ // Check for unsupported transactions.
+ CYG_ASSERT (count > 0, "DSPI: Null transfer requested.");
+
+ // We check that count is a multiple of two in order
+ // to carry out the 16-bit transfer.
+ if (dspi_device->clocking.bus_16bit) {
+ CYG_ASSERT (!(count & 1),
+ "DSPI: Misaligned data in 16-bit transfer.");
+ }
+
+ // Perform null transfer
+ DEBUG2_PRINTF("cyg_transaction_tick()\n");
+ spi_transaction_do (device, true, polled, count, NULL, NULL, false);
+}
+
+//-----------------------------------------------------------------------------
+// Terminate a SPI transaction, disabling the SPI controller.
+
+static void dspi_transaction_end(cyg_spi_device* device)
+{
+ cyg_spi_freescale_dspi_bus_t* dspi_bus =
+ (cyg_spi_freescale_dspi_bus_t*) device->spi_bus;
+ cyg_spi_freescale_dspi_device_t* dspi_device =
+ (cyg_spi_freescale_dspi_device_t*) device;
+
+ const cyghwr_hal_freescale_dma_set_t *dma_set_p = dspi_bus->setup_p->dma_set_p;
+ cyghwr_hal_freescale_edma_t *edma_p;
+ cyghwr_devs_freescale_dspi_t* dspi_p = dspi_bus->setup_p->dspi_p;
+
+ DEBUG2_PRINTF("cyg_transaction_end() chip_sel = %d\n", dspi_device->chip_sel);
+ if(dma_set_p) {
+ edma_p = dma_set_p->edma_p;
+ hal_freescale_edma_erq_disable(edma_p, SPI_DMA_CHAN_I(dma_set_p, TX));
+ hal_freescale_edma_erq_disable(edma_p, SPI_DMA_CHAN_I(dma_set_p, RX));
+ }
+
+ if(dspi_device->chip_sel){
+ // Clear peripheral CS by executing a dummy 4 bit transfer.
+ dspi_p->pushr = PUSHR_NULL | FREESCALE_DSPI_PUSHR_EOQ_M |
+ FREESCALE_DSPI_PUSHR_CTAS(1);
+ while(!(dspi_p->sr & FREESCALE_DSPI_SR_EOQF_M));
+ DSPI_EOQ_CLEAR(dspi_p);
+ dspi_fifo_drain(dspi_p);
+ dspi_device->chip_sel = 0;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Get DSPI configuration parameter
+
+static int dspi_get_config (cyg_spi_device* device, cyg_uint32 key,
+ void* buf, cyg_uint32* len)
+{
+ cyg_spi_freescale_dspi_bus_t* dspi_bus =
+ (cyg_spi_freescale_dspi_bus_t*) device->spi_bus;
+ cyg_spi_freescale_dspi_device_t* dspi_device =
+ (cyg_spi_freescale_dspi_device_t*) device;
+ cyg_uint32* data_p = buf;
+
+ switch (key) {
+ case CYG_IO_GET_CONFIG_SPI_CLOCKRATE :
+ // Sanity check
+ if (NULL == len) {
+ CYG_ASSERT (false, "Freescale DSPI:"
+ " Null pointer as len argument for dspi_get_config().");
+ return -1;
+ } else if (sizeof(cyg_uint32) != *len) {
+ CYG_ASSERT (false, "Freescale DSPI:"
+ " Invalid length with dspi_get_config().");
+ return -1;
+ } else if (NULL == buf) {
+ CYG_ASSERT (false, "Freescale DSPI:"
+ " Null poiter as buf argument for dspi_get_config().");
+ return -1;
+ } else {
+ cyg_uint32 ctar, dbr, br, pbr;
+
+ ctar = dspi_device->clocking.dspi_ctar;
+ dbr = (ctar & FREESCALE_DSPI_CTAR_DBR_M) >>
+ FREESCALE_DSPI_CTAR_DBR_S;
+ br = (ctar & FREESCALE_DSPI_CTAR_BR_M) >>
+ FREESCALE_DSPI_CTAR_BR_S;
+ pbr = (ctar & FREESCALE_DSPI_CTAR_PBR_M) >>
+ FREESCALE_DSPI_CTAR_PBR_S;
+ *data_p = (dspi_bus->clock_freq * (1+dbr)) / (pbr * br);
+
+ DEBUG2_PRINTF("DSPI Get Config: baud = %d\n", *data_p);
+
+ return 0;
+ }
+
+ default :
+ break;
+ }
+ return -1;
+}
+
+//-----------------------------------------------------------------------------
+// Change some SPI device configuration parameters
+
+static int dspi_set_config(cyg_spi_device* device, cyg_uint32 key,
+ const void* buf, cyg_uint32* len)
+{
+ cyg_spi_freescale_dspi_device_t* dspi_device =
+ (cyg_spi_freescale_dspi_device_t*) device;
+ cyg_spi_freescale_dspi_bus_t* dspi_bus =
+ (cyg_spi_freescale_dspi_bus_t*) device->spi_bus;
+
+ cyg_uint32 regval;
+ ctar_br_t brs;
+
+ switch (key) {
+ case CYG_IO_SET_CONFIG_SPI_CLOCKRATE :
+ // Sanity check
+ if (NULL == len) {
+ CYG_ASSERT (false, "Freescale DSPI:"
+ " Null pointer as len argument for dspi_set_config().");
+ return -1;
+ } else if (sizeof(cyg_uint32) != *len) {
+ CYG_ASSERT (false, "Freescale DSPI:"
+ " Invalid length with dspi_set_config().");
+ return -1;
+ } else if (NULL == buf) {
+ CYG_ASSERT (false, "Freescale DSPI:"
+ " Null pointer as buf argument for dspi_set_config().");
+ return -1;
+ } else {
+ // Get divider bits
+ if (!dspi_ctar_brbf(&dspi_device->clocking, &brs,
+ ctar_br, ctar_pbr, (cyg_uint32 *)buf, dspi_bus->clock_freq))
+ {
+ // Update the cache of the configuration register settings.
+ regval = dspi_device->clocking.dspi_ctar;
+ regval &= ~(FREESCALE_DSPI_CTAR_BR_M |
+ FREESCALE_DSPI_CTAR_PBR_M);
+ regval |= FREESCALE_DSPI_CTAR_BR(brs.br) |
+ FREESCALE_DSPI_CTAR_PBR(brs.pbr);
+ dspi_device->clocking.dspi_ctar = regval;
+
+ return 0;
+
+ } else {
+ CYG_ASSERT (false, "Freescale DSPI:"
+ " Cannot run bus as slowly as requested.");
+ return -1;
+ }
+ }
+ default :
+ break;
+ }
+ return -1;
+}
+
+#if DEBUG_SPI
+//----------------------------------------------------------------------------
+// Print out a DSPI array state
+// Helper for cyghwr_devs_freescale_dspi_diag()
+
+void cyghwr_devs_freescale_dspi_diag_array(char* name_p,
+ volatile cyg_uint32* array_p,
+ cyg_uint32 array_n)
+{
+ diag_printf("%s %p[%u]: ", name_p, array_p, array_n);
+ for(; array_n; array_n--) {
+ diag_printf(" 0x%08x", *array_p++);
+ }
+ diag_printf("\n");
+}
+
+//----------------------------------------------------------------------------
+// Print out DSPI state
+
+void cyghwr_devs_freescale_dspi_diag(cyg_spi_freescale_dspi_bus_t* dspi_bus_p)
+{
+ cyghwr_devs_freescale_dspi_t* dspi_p = dspi_bus_p->setup_p->dspi_p;
+
+ diag_printf("DSPI %p\n", dspi_p);
+ diag_printf(" MCR = 0x%08x TCR = 0x%08x\n", dspi_p->mcr, dspi_p->tcr);
+ cyghwr_devs_freescale_dspi_diag_array(" CTAR", dspi_p->ctar,
+ CYGHWR_DEVS_SPI_FREESCALE_DSPI_CTAR_NUM);
+ diag_printf(" SR = 0x%08x RSER = 0x%08x PUSHR = 0x%08x POPR = 0x%08x\n",
+ dspi_p->sr, dspi_p->rser, dspi_p->pushr, dspi_p->popr);
+ cyghwr_devs_freescale_dspi_diag_array(" TXFR", dspi_p->txfr, dspi_bus_p->txfifo_n);
+ cyghwr_devs_freescale_dspi_diag_array(" RXFR", dspi_p->rxfr, dspi_bus_p->rxfifo_n);
+}
+#endif // DEBUG_SPI
+
+#endif // defined(CYGHWR_DEVS_SPI_FREESCALE_DSPIx)
+
+//=============================================================================
diff --git a/ecos/packages/devs/spi/freescale/dspi/current/tests/spi_loopback.c b/ecos/packages/devs/spi/freescale/dspi/current/tests/spi_loopback.c
new file mode 100644
index 0000000..6e70e0c
--- /dev/null
+++ b/ecos/packages/devs/spi/freescale/dspi/current/tests/spi_loopback.c
@@ -0,0 +1,285 @@
+//=============================================================================
+//
+// spi_loopback.c
+//
+// Standalone SPI loopback test.
+//
+//=============================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2012 Free Software Foundation, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later
+// version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with eCos; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// As a special exception, if other files instantiate templates or use
+// macros or inline functions from this file, or you compile this file
+// and link it with other works to produce a work based on this file,
+// this file does not by itself cause the resulting work to be covered by
+// the GNU General Public License. However the source code for this file
+// must still be made available in accordance with section (3) of the GNU
+// General Public License v2.
+//
+// This exception does not invalidate any other reasons why a work based
+// on this file might be covered by the GNU General Public License.
+// -------------------------------------------
+// ####ECOSGPLCOPYRIGHTEND####
+//=============================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Ilija Kocho
+// Original: Chris Holgate
+// Date: 2012-12-27
+// Purpose: Freescale DSPI loopback test
+// Description: Standalone SPI loopback test.
+// Usage: Compile as a standalone application.
+//
+//####DESCRIPTIONEND####
+//
+//=============================================================================
+
+//=============================================================================
+// This is a quick loopback test for the Freescale DSPI SPI driver. It only checks
+// the data transfer functionality - chip select handling will require
+// testing with external devices. In order to run the test, the MOSI and
+// MISO pins for the test port need to be shorted together to provide an
+// external loopback. Don't do this on a bus which has external devices
+// attached unless you first make sure that none of them are connected to
+// the chip select used by the test harness.
+// The default port and chip select used for this test are SPI bus 1,
+// chip select 0. These can be changed by editing the loopback_device
+// data structure directly.
+// Note that this is intended to be run as a standalone test and not as part
+// of the standard board tests since it requires a hardware modification.
+//=============================================================================
+
+#include <cyg/infra/cyg_type.h>
+#include <cyg/infra/testcase.h> // Test macros
+
+#include <cyg/infra/cyg_ass.h> // Assertion macros
+#include <cyg/infra/diag.h> // Diagnostic output
+
+#include <cyg/hal/hal_arch.h> // CYGNUM_HAL_STACK_SIZE_TYPICAL
+#include <cyg/kernel/kapi.h>
+
+#include <cyg/io/spi.h> // Common SPI API
+#include <cyg/io/spi_freescale_dspi.h> // Freescale DSPI data structures
+
+#include <string.h>
+
+//---------------------------------------------------------------------------
+// Thread data structures.
+
+cyg_uint8 stack [CYGNUM_HAL_STACK_SIZE_TYPICAL];
+cyg_thread thread_data;
+cyg_handle_t thread_handle;
+
+externC cyg_spi_freescale_dspi_bus_t cyg_spi_dspi_bus1;
+
+//---------------------------------------------------------------------------
+// SPI loopback device driver data structures.
+
+CYG_DEVS_SPI_FREESCALE_DSPI_DEVICE(
+ loopback_device, // Device name
+ 1, //SPI bus
+ 0, // Dev num
+ 8, // Frame size
+ 0, // Clock pol
+ 0, // Clock phase
+ 6000000, // Clock speed
+ 1, // CS assert delay
+ 1, // CS negate delay
+ 1, // Delay between transfers
+ 1000, // Delay unit [ns]
+ 0 // Double baud rate
+);
+
+//---------------------------------------------------------------------------
+
+static int errors = 0;
+
+const char tx_data0[] = "0123456789a123456789b123456789c123456789d123456789e";
+const char tx_data1[] = "Performing extended API test first transaction..|";
+const char tx_data2[] = "Testing extended API for a second transaction!";
+
+char rx_data [256];
+char rx_data1 [256];
+char rx_data2 [256];
+
+static void memclr(char *dest_p, cyg_uint32 byte_n)
+{
+ while(byte_n--) {
+ *dest_p++ = 0;
+ }
+}
+
+
+//---------------------------------------------------------------------------
+// Run single loopback transaction using simple transfer API call.
+
+void run_test_tick (cyg_bool polled, cyg_uint32 count)
+{
+ diag_printf ("Test 0 : Tick (polled = %d).\n", polled ? 1 : 0);
+ cyg_spi_tick(&loopback_device, polled, count);
+ diag_printf (" Tick end\n");
+}
+
+void run_test_1 (cyg_bool polled, const char* tx_data_p, cyg_uint32 count)
+{
+ diag_printf ("Test 1 : Simple transfer test polled = %d, count=%d\n",
+ polled ? 1 : 0, count);
+ memclr(rx_data1, sizeof(rx_data1));
+ memclr(rx_data2, sizeof(rx_data1));
+ cyg_spi_transfer (&loopback_device, polled, count,
+ (const cyg_uint8*) tx_data_p, (cyg_uint8*) &rx_data[0]);
+ diag_printf (" Tx data : %s\n", tx_data_p);
+ diag_printf (" Rx data : %s 0x%02x\n", rx_data, rx_data[0]);
+
+ if (memcmp (tx_data_p, rx_data, count) != 0) {
+ errors++;
+ diag_printf("Simple transfer loopback failed - mismatched data.\n");
+ }
+}
+
+//---------------------------------------------------------------------------
+// Run two loopback transactions using extended transfer API.
+
+void run_test_2 (cyg_bool polled)
+{
+ diag_printf ("Test 2 : Extended API test (polled = %d).\n", polled ? 1 : 0);
+ memclr(rx_data1, sizeof(rx_data1));
+ memclr(rx_data2, sizeof(rx_data1));
+ cyg_spi_transaction_begin (&loopback_device);
+ cyg_spi_transaction_transfer (&loopback_device, polled, sizeof (tx_data1),
+ (const cyg_uint8*) &tx_data1[0], (cyg_uint8*) &rx_data1[0], false);
+ cyg_spi_transaction_transfer (&loopback_device, polled, sizeof (tx_data2),
+ (const cyg_uint8*) &tx_data2[0], (cyg_uint8*) &rx_data2[0], true);
+ cyg_spi_transaction_end (&loopback_device);
+
+ diag_printf (" Tx data 1 (%u Bytes): %s\n", sizeof(tx_data1), tx_data1);
+ diag_printf (" Rx data 1 : %s\n", rx_data1);
+ diag_printf (" Tx data 2 (%u Bytes): %s\n", sizeof(tx_data2), tx_data2);
+ diag_printf (" Rx data 2 : %s\n", rx_data2);
+ if (memcmp (tx_data1, rx_data1, sizeof (tx_data1)) != 0) {
+ errors++;
+ diag_printf("Simple transfer loopback failed - mismatched data (transfer 1).\n");
+ }
+ if (memcmp (tx_data2, rx_data2, sizeof (tx_data2)) != 0) {
+ errors++;
+ diag_printf("Simple transfer loopback failed - mismatched data (transfer 2).\n");
+ }
+}
+
+void run_test_3 (cyg_bool polled)
+{
+ diag_printf ("Test 3 : Extended API test (polled = %d).\n", polled ? 1 : 0);
+ memclr(rx_data1, sizeof(rx_data1));
+ memclr(rx_data2, sizeof(rx_data1));
+
+ cyg_spi_transaction_begin (&loopback_device);
+ cyg_spi_transaction_transfer (&loopback_device, polled, sizeof (tx_data1),
+ (const cyg_uint8*) &tx_data1[0], (cyg_uint8*) &rx_data1[0], false);
+ cyg_spi_transaction_transfer (&loopback_device, polled, sizeof (tx_data2),
+ (const cyg_uint8*) &tx_data2[0], (cyg_uint8*) &rx_data2[0], true);
+ cyg_spi_transaction_end (&loopback_device);
+ diag_printf (" Tx data 1 (%u Bytes): %s\n", sizeof(tx_data1), tx_data1);
+ diag_printf (" Rx data 31 : %s\n", rx_data1);
+ diag_printf (" Tx data 2 (%u Bytes): %s\n", sizeof(tx_data2), tx_data2);
+ diag_printf (" Rx data 32 : %s\n", rx_data2);
+
+ if (memcmp (tx_data1, rx_data1, sizeof (tx_data1)) != 0) {
+ errors++;
+ diag_printf("Simple transfer loopback failed - mismatched data (transfer 1).\n");
+ }
+ if (memcmp (tx_data2, rx_data2, sizeof (tx_data2)) != 0) {
+ errors++;
+ diag_printf("Simple transfer loopback failed - mismatched data (transfer 2).\n");
+ }
+}
+
+void run_test_4 (cyg_bool polled)
+{
+ diag_printf ("Test 4 : Extended API test NULL transfer (polled = %d).\n", polled ? 1 : 0);
+ memclr(rx_data1, sizeof(rx_data1));
+ memclr(rx_data2, sizeof(rx_data1));
+
+ cyg_spi_transaction_begin (&loopback_device);
+ cyg_spi_transaction_transfer (&loopback_device, polled, sizeof (tx_data1),
+ (const cyg_uint8*) NULL, NULL, true);
+ cyg_spi_transaction_end (&loopback_device);
+ diag_printf (" Tx data 41 (%u Bytes): %s\n", sizeof(tx_data1), tx_data1);
+ diag_printf (" Rx data 1 : %s\n", rx_data1);
+ diag_printf (" Tx data 42 (%u Bytes): %s\n", sizeof(tx_data2), tx_data2);
+ diag_printf (" Rx data 2 : %s\n", rx_data2);
+
+ if (memcmp (rx_data1, rx_data2, sizeof (tx_data1)) != 0) {
+ errors++;
+ diag_printf("Simple transfer loopback failed - mismatched data.\n");
+ errors++;
+ }
+}
+
+
+//---------------------------------------------------------------------------
+// Run all SPI interface loopback tests.
+
+
+void run_tests (void)
+{
+ bool polled = true;
+ diag_printf ("Running Freescale Kinetis/MPC5xxx DSPI driver loopback tests.\n");
+
+ diag_printf ("\nPolled\n");
+ run_test_tick (polled, 1024);
+ run_test_1 (polled, &tx_data0[3], 4);
+ run_test_2 (polled);
+ run_test_3 (polled);
+ run_test_4 (polled);
+
+ polled = false;
+ diag_printf ("\nInterrupt driven.\n");
+ run_test_tick (polled,2048);
+ run_test_1 (polled, &tx_data0[7], 10);
+ run_test_2 (polled);
+ run_test_3 (polled);
+ run_test_4 (polled);
+
+ if(errors)
+ CYG_TEST_FAIL("Errors detected");
+ else
+ CYG_TEST_PASS_FINISH ("Loopback tests ran OK");
+}
+
+//---------------------------------------------------------------------------
+// User startup - tests are run in their own thread.
+
+void cyg_user_start(void)
+{
+ CYG_TEST_INIT();
+ cyg_thread_create(
+ 10, // Arbitrary priority
+ (cyg_thread_entry_t*) run_tests, // Thread entry point
+ 0, //
+ "test_thread", // Thread name
+ &stack[0], // Stack
+ CYGNUM_HAL_STACK_SIZE_TYPICAL, // Stack size
+ &thread_handle, // Thread handle
+ &thread_data // Thread data structure
+ );
+ cyg_thread_resume(thread_handle);
+ cyg_scheduler_start();
+}
+
+//=============================================================================