Mercurial > nand-ecoscentric
changeset 1794:6531d33a6737
Added support for SPI on the EB55
| author | asl |
|---|---|
| date | Tue, 05 Oct 2004 08:28:34 +0000 |
| parents | f73c51496d30 |
| children | 68f7128db71e |
| files | packages/devs/spi/arm/at91/current/ChangeLog packages/devs/spi/arm/at91/current/cdl/spi_at91.cdl packages/devs/spi/arm/at91/current/include/spi_at91.h packages/devs/spi/arm/at91/current/src/spi_at91.c packages/devs/spi/arm/at91/current/src/spi_at91_init.cxx packages/devs/spi/arm/eb55/current/ChangeLog packages/devs/spi/arm/eb55/current/cdl/spi_eb55.cdl packages/devs/spi/arm/eb55/current/include/spi_eb55.h packages/devs/spi/arm/eb55/current/src/spi_eb55.c |
| diffstat | 9 files changed, 1195 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/packages/devs/spi/arm/at91/current/ChangeLog @@ -0,0 +1,54 @@ +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. + + + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, 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., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. +// +// 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#### +//===========================================================================
new file mode 100644 --- /dev/null +++ b/packages/devs/spi/arm/at91/current/cdl/spi_at91.cdl @@ -0,0 +1,100 @@ +# ==================================================================== +# +# 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 Red Hat, 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., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. +## +## This exception does not invalidate any other reasons why a work based on +## this file might be covered by the GNU General Public License. +## +## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +## at http://sources.redhat.com/ecos/ecos-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 + hardware + include_dir cyg/io + compile spi_at91.c + compile -library=libextras.a spi_at91_init.cxx + + cdl_option CYGHWR_DEVS_SPI_ARM_AT91_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_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
new file mode 100644 --- /dev/null +++ b/packages/devs/spi/arm/at91/current/include/spi_at91.h @@ -0,0 +1,114 @@ +#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 Red Hat, 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., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-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_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 bus + +externC cyg_spi_at91_bus_t cyg_spi_at91_bus; + +//----------------------------------------------------------------------------- + +#endif // CYGONCE_DEVS_SPI_ARM_AT91_H + +//----------------------------------------------------------------------------- +// End of spi_at91.h
new file mode 100644 --- /dev/null +++ b/packages/devs/spi/arm/at91/current/src/spi_at91.c @@ -0,0 +1,573 @@ +//========================================================================== +// +// 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 Red Hat, 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., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-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 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 + +cyg_spi_at91_bus_t cyg_spi_at91_bus = { + .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 +}; + +CYG_SPI_DEFINE_BUS_TABLE(cyg_spi_at91_device_t, 0); + +// ------------------------------------------------------------------------- + +void +cyg_spi_at91_bus_init(void) +{ + // Create and attach SPI interrupt object + cyg_drv_interrupt_create(CYGNUM_HAL_INTERRUPT_SPI, + 4, + (cyg_addrword_t)&cyg_spi_at91_bus, + spi_at91_ISR, + spi_at91_DSR, + &cyg_spi_at91_bus.spi_interrupt_handle, + &cyg_spi_at91_bus.spi_interrupt); + + cyg_drv_interrupt_attach(cyg_spi_at91_bus.spi_interrupt_handle); + + // Init transfer mutex and condition + cyg_drv_mutex_init(&cyg_spi_at91_bus.transfer_mx); + cyg_drv_cond_init(&cyg_spi_at91_bus.transfer_cond, + &cyg_spi_at91_bus.transfer_mx); + + // Init flags + cyg_spi_at91_bus.transfer_end = true; + cyg_spi_at91_bus.cs_up = false; + + // Soft reset the SPI controller + HAL_WRITE_UINT32(AT91_SPI+AT91_SPI_CR, AT91_SPI_CR_SWRST); + + // Configure SPI pins + + // 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 + // inbetween transactions. + + // Put SPI MISO, MOIS and SPCK pins into peripheral mode + HAL_WRITE_UINT32(AT91_SPI_PIO+AT91_PIO_PDR, AT91_PIO_PSR_SPCK | + AT91_PIO_PSR_MISO | + AT91_PIO_PSR_MOIS); + + // Put SPI chip select pins in IO output mode + HAL_WRITE_UINT32(AT91_SPI_PIO+AT91_PIO_SODR, AT91_SPI_PIO_NPCS(0x0F)); + HAL_WRITE_UINT32(AT91_SPI_PIO+AT91_PIO_PER, AT91_SPI_PIO_NPCS(0x0F)); + HAL_WRITE_UINT32(AT91_SPI_PIO+AT91_PIO_OER, AT91_SPI_PIO_NPCS(0x0F)); + + // Call upper layer bus init + CYG_SPI_BUS_COMMON_INIT(&cyg_spi_at91_bus.spi_bus); +} + +// ------------------------------------------------------------------------- + +static cyg_uint32 +spi_at91_ISR(cyg_vector_t vector, cyg_addrword_t data) +{ + cyg_uint32 stat; + + // Read the status register and disable + // the SPI int events that have occoured + + HAL_READ_UINT32(AT91_SPI+AT91_SPI_SR, stat); + HAL_WRITE_UINT32(AT91_SPI+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 completition + + HAL_READ_UINT32(AT91_SPI+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 / (2*dev->cl_brate); + + 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 / (64*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_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 + HAL_WRITE_UINT32(AT91_SPI_PIO+AT91_PIO_CODR, + AT91_SPI_PIO_NPCS(~dev->dev_num)); +#else + HAL_WRITE_UINT32(AT91_SPI_PIO+AT91_PIO_CODR, + AT91_SPI_PIO_NPCS((~(1<<dev->dev_num)) & 0x0F)); +#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); + HAL_WRITE_UINT32(AT91_SPI_PIO+AT91_PIO_SODR, AT91_SPI_PIO_NPCS(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(AT91_SPI+AT91_SPI_RPR, (cyg_uint32)rx_data); + HAL_WRITE_UINT32(AT91_SPI+AT91_SPI_RCR, (cyg_uint32)tr_count); + } + + // Set tx buf pointer and counter + HAL_WRITE_UINT32(AT91_SPI+AT91_SPI_TPR, (cyg_uint32)tx_data); + HAL_WRITE_UINT32(AT91_SPI+AT91_SPI_TCR, (cyg_uint32)tr_count); + + // Enable the SPI int events we are interested in + HAL_WRITE_UINT32(AT91_SPI+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(CYGNUM_HAL_INTERRUPT_SPI); + + // Wait for its completition + 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(AT91_SPI+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; + + // Transmit and receive byte by byte + while (count-- > 0) + { + // Wait for transmit data register empty + do + { + HAL_READ_UINT32(AT91_SPI+AT91_SPI_SR, val); + } while ( !(val & AT91_SPI_SR_TDRE) ); + + // Send next byte over the wire + val = *tx_data++; + HAL_WRITE_UINT32(AT91_SPI+AT91_SPI_TDR, val); + + // Wait for reveive data register full + do + { + HAL_READ_UINT32(AT91_SPI+AT91_SPI_SR, val); + } while ( !(val & AT91_SPI_SR_RDRF) ); + + // Store received byte + HAL_READ_UINT32(AT91_SPI+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_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(AT91_SPI+AT91_SPI_CSR0, val); + + // Enable SPI clock + HAL_WRITE_UINT32(AT91_PMC+AT91_PMC_PCER, AT91_PMC_PCER_SPI); + + // Enable the SPI controller + HAL_WRITE_UINT32(AT91_SPI+AT91_SPI_CR, AT91_SPI_CR_SPIEN); + + // Put SPI bus into master mode + if (1 == at91_spi_dev->cl_div32) + HAL_WRITE_UINT32(AT91_SPI+AT91_SPI_MR, AT91_SPI_MR_MSTR | + AT91_SPI_MR_DIV32); + else + HAL_WRITE_UINT32(AT91_SPI+AT91_SPI_MR, AT91_SPI_MR_MSTR); +} + +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) +{ + // Disable the SPI controller + HAL_WRITE_UINT32(AT91_SPI+AT91_SPI_CR, AT91_SPI_CR_SPIDIS); + + // Disable SPI clock + HAL_WRITE_UINT32(AT91_PMC+AT91_PMC_PCDR, AT91_PMC_PCER_SPI); + + 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
new file mode 100644 --- /dev/null +++ b/packages/devs/spi/arm/at91/current/src/spi_at91_init.cxx @@ -0,0 +1,68 @@ +//========================================================================== +// +// 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 Red Hat, 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., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Savin Zlobec <savin@elatec.si> +// Date: 2004-08-25 +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include <cyg/infra/cyg_type.h> + +// ------------------------------------------------------------------------- + +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_IO); + +// ------------------------------------------------------------------------- +// EOF spi_at91_init.cxx
new file mode 100644 --- /dev/null +++ b/packages/devs/spi/arm/eb55/current/ChangeLog @@ -0,0 +1,48 @@ +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. + + + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, 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., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. +// +// 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#### +//===========================================================================
new file mode 100644 --- /dev/null +++ b/packages/devs/spi/arm/eb55/current/cdl/spi_eb55.cdl @@ -0,0 +1,98 @@ +# ==================================================================== +# +# 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 Red Hat, 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., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. +## +## This exception does not invalidate any other reasons why a work based on +## this file might be covered by the GNU General Public License. +## +## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +## at http://sources.redhat.com/ecos/ecos-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_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
new file mode 100644 --- /dev/null +++ b/packages/devs/spi/arm/eb55/current/include/spi_eb55.h @@ -0,0 +1,63 @@ +#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 Red Hat, 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., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-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
new file mode 100644 --- /dev/null +++ b/packages/devs/spi/arm/eb55/current/src/spi_eb55.c @@ -0,0 +1,77 @@ +//========================================================================== +// +// 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 Red Hat, 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., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-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 +static 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 +}; + +cyg_spi_device *cyg_spi_dataflash_dev0 = &spi_dataflash_dev0.spi_device; + +// ------------------------------------------------------------------------- +// EOF spi_eb55.c
