diff options
Diffstat (limited to 'firmwares/wifishield/wifiHD/src/avr32_spi.c')
-rw-r--r-- | firmwares/wifishield/wifiHD/src/avr32_spi.c | 394 |
1 files changed, 0 insertions, 394 deletions
diff --git a/firmwares/wifishield/wifiHD/src/avr32_spi.c b/firmwares/wifishield/wifiHD/src/avr32_spi.c deleted file mode 100644 index 739fb28..0000000 --- a/firmwares/wifishield/wifiHD/src/avr32_spi.c +++ /dev/null @@ -1,394 +0,0 @@ -/*! \page License - * Copyright (C) 2009, H&D Wireless AB All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. The name of H&D Wireless AB may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY H&D WIRELESS AB ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND - * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include <gpio.h> -#include <intc.h> -#include <string.h> -#include <stdint.h> -#include <stdlib.h> -#include <wl_spi.h> -#include <printf-stdarg.h> -#include <board_init.h> - -#define ARRAY_SIZE(a) sizeof(a) / sizeof(a[0]) - -__attribute__((__interrupt__)) void avr32_irq_handler(void); -void owl_spi_mdelay(uint32_t ms); - -int owl_spi_init(U8 *flags) -{ -#ifdef _ASSERT_ENABLE_ /* To silence warning if Assert() macro is empty */ - volatile avr32_pm_t *pm = &AVR32_PM; -#endif - - volatile avr32_spi_t *spi = &WL_SPI; -#if WL_SPI_CS == 1 - volatile avr32_spi_csr1_t* CSR = &spi->CSR1; -#elif WL_SPI_CS == 2 - volatile avr32_spi_csr2_t* CSR = &spi->CSR2; -#elif WL_SPI_CS == 3 - volatile avr32_spi_csr3_t* CSR = &spi->CSR3; -#elif SPI_CS == 0 - volatile avr32_spi_csr0_t* CSR = &spi->CSR0; -#endif - -#ifndef WITH_NO_DMA - volatile avr32_pdca_channel_t *pdca_tx = &AVR32_PDCA.channel[0]; - volatile avr32_pdca_channel_t *pdca_rx = &AVR32_PDCA.channel[1]; -#endif - -#ifndef WL_IRQ_PIN - *flags = SPI_FLAG_POLL; -#else - *flags = 0; -#endif - - -#ifdef WL_IRQ_PIN - /* input, irq */ - gpio_enable_gpio_pin(WL_IRQ_PIN); - gpio_enable_pin_pull_up(WL_IRQ_PIN); -#endif - -//#ifdef WL_RESET_PIN -// /* reset pin */ -// gpio_enable_gpio_pin(WL_RESET_PIN); -// gpio_set_gpio_pin(WL_RESET_PIN); -//#endif - - -#ifdef WL_POWER_PIN - /* power off the device */ - gpio_enable_gpio_pin(WL_POWER_PIN); - gpio_set_gpio_pin(WL_POWER_PIN); -#endif - -#ifdef WL_SHUTDOWN_PIN - gpio_enable_gpio_pin(WL_SHUTDOWN_PIN); - -#ifdef WL_NO_INTERNAL_RESET /* never defined for SPB104/SPB105 */ - gpio_clr_gpio_pin(WL_SHUTDOWN_PIN); -#endif - -#ifdef WL_EXTERNAL_RESET - gpio_enable_gpio_pin(WL_RESET_PIN); -#endif - -#endif /* WL_SHUTDOWN_PIN */ - -#ifdef WL_POWER_PIN - /* power on the device */ - gpio_clr_gpio_pin(WL_POWER_PIN); -#endif - -#ifdef WL_SHUTDOWN_PIN - -#ifdef WL_NO_INTERNAL_RESET /* never defined for SPB104/SPB105 */ - owl_spi_mdelay(5); - gpio_set_gpio_pin(WL_SHUTDOWN_PIN); - -#elif WL_EXTERNAL_RESET - owl_spi_mdelay(5); - gpio_set_gpio_pin(WL_SHUTDOWN_PIN); - - owl_spi_mdelay(20); - //delay_ms(10); //2ms - - /* reset pin */ - gpio_set_gpio_pin(WL_RESET_PIN); - -#else - - /* The shutdown pin will go high once the device is powered */ - { -#define SHUTDOWN_TIMEOUT 350 - uint32_t shutdown_timer = 0; - while (gpio_get_pin_value(WL_SHUTDOWN_PIN) == 0) { - if (shutdown_timer > SHUTDOWN_TIMEOUT) - { - printk("Timeout WL Shutdown\n"); - return -1; - } - owl_spi_mdelay(5); - shutdown_timer += 5; - } - } -#endif /* WL_NO_INTERNAL_RESET */ - -#else - /* We need to make a guess about the time needed to power the device, - * this will depend on the hardware design. - */ - owl_spi_mdelay(5); -#endif /* WL_SHUTDOWN_PIN */ - - /* Note: SPI0 clock enabled at reset in pm->pbamask (see 13.6.3) */ - Assert(pm->pbamask & (1 << 5)); - - /* Note: GPIO clock enabled at reset in pm->pbamask (see 13.6.3) */ - Assert(pm->pbamask & (1 << 1)); -#ifdef WL_IRQ_PIN - /* 22.4.7: "In every port there are four interrupt lines - * connected to the interrupt controller. Every eigth - * interrupts in the port are ored together to form an - * interrupt line." - * - * WL_IRQ_# = (WL_IRQ_PIN / 32) * 4 + (WL_IRQ_PIN / 8) % 4 - * 62 => 1 * 4 + 3 = 7 - */ - INTC_register_interrupt(&avr32_irq_handler, WL_IRQ, AVR32_INTC_INT0); -#endif - -#ifndef WITH_NO_DMA - INTC_register_interrupt(&avr32_irq_handler, AVR32_PDCA_IRQ_0, - AVR32_INTC_INT0); - INTC_register_interrupt(&avr32_irq_handler, AVR32_PDCA_IRQ_1, - AVR32_INTC_INT0); - pdca_tx->IER.terr = 1; - pdca_rx->IER.terr = 1; -#endif - -#ifdef WL_SPI_CLOCK_DIVIDER - CSR->scbr = WL_SPI_CLOCK_DIVIDER; -#else - CSR->scbr = 2; -#endif - - /* Use max width of TDR register, 16 bit transfers */ - CSR->bits = 0x8; - - /* Make sure that we can hold CS low until transfer is completed, e.g - * LASTXFER is set in TDR. - */ - CSR->csaat = 1; - - /* NRG component requires clock polarity high */ - CSR->cpol = 1; - - -#ifdef WL_IRQ_PIN - /* make sure to clear any pending bits in ifr here. */ - gpio_clear_pin_interrupt_flag(WL_IRQ_PIN); -#endif - - return 0; -} - -#ifndef WITH_NO_DMA -static void dma_txrx(const U8* in, U8* out, U16 len) -{ - volatile avr32_pdca_channel_t *pdca_tx = &AVR32_PDCA.channel[0]; - volatile avr32_pdca_channel_t *pdca_rx = &AVR32_PDCA.channel[1]; - - /* setup tx */ - pdca_tx->mar = (U32) in; - pdca_tx->PSR.pid = WL_PDCA_PID_TX; - pdca_tx->tcr = len / 2; - pdca_tx->MR.size = 1; /* 2-byte */ - pdca_tx->IER.trc = 1; - - /* setup rx */ - pdca_rx->mar = (U32) out; - pdca_rx->PSR.pid = WL_PDCA_PID_RX; - pdca_rx->tcr = len / 2; - pdca_rx->MR.size = 1; /* 2-byte */ - pdca_rx->IER.trc = 1; - - /* start dma's. for some reason rx must be started prior to tx */ - pdca_rx->CR.ten = 1; - pdca_tx->CR.ten = 1; - - /* blocking wait until transfer is completed */ - while (!(pdca_tx->ISR.trc && pdca_rx->ISR.trc)); -} -#endif - -/* access data using byte pointers since we might get unaligned - * data from lwip. The cpu will issue a data abort if we try - * to access data which is not properly aligned. See data sheet. - * - * Note that fifo_txrx() doesn't handle the case where len is not a - * multiple of two bytes properly. - * - * However, there is no actual case where len is odd at the same time - * as the "out" pointer is non-NULL; therefore I think that in practice, - * we'll not write beyond the end of the "out" array. - * - * The extra unknown byte fetched from the in pointer will be discarded - * by the device since a length field included in the packet header will inform - * the device of the actual number of valid bytes (this implementation is - * kind of hidden inside the library). - */ -static void fifo_txrx(const U8 *in, U8* out, U16 len) -{ - volatile avr32_spi_t *spi = &WL_SPI; - UnionCPtr in_ptr; - UnionPtr out_ptr; - U32 sr; - - Assert(len); - - in_ptr.u8ptr = in; - out_ptr.u8ptr = out; - - while (len) { - U16 rdr; - union { - avr32_spi_tdr_t TDR; - U32 tdr; - } reg = { { 0 } }; - - while (!spi->SR.tdre); - while (!spi->SR.txempty); - - /* prepare tx data register contents */ - if (in_ptr.u8ptr) { - reg.TDR.td |= (in_ptr.u8ptr[0] << 8) | in_ptr.u8ptr[1]; - in_ptr.u16ptr++; - } - else - reg.TDR.td |= 0xffff; - - /* perform tx */ - spi->tdr = reg.tdr; - - /* wait until rx is ready */ - while (!spi->SR.rdrf); - - /* fetch rx data */ - rdr = spi->RDR.rd; - if (out_ptr.u8ptr) { - out_ptr.u8ptr[0] = (rdr >> 8) & 0xff; - out_ptr.u8ptr[1] = rdr & 0xff; - out_ptr.u16ptr++; - } - - if (len >= 2) - len -= 2; - else - len = 0; - } - - sr = spi->sr; - Assert(!(sr & AVR32_SPI_SR_OVRES_MASK)); - Assert(!(sr & AVR32_SPI_SR_MODF_MASK)); -} - -void owl_spi_txrx(const U8 *in, U8* out, U16 len) -{ -#ifndef WITH_NO_DMA - static uint8_t buf[MAX_BLOCK_LEN]; - - /* unaligned data or odd number of bytes, then skip dma */ - if ((U32) in % 4 || (U32) out % 4 || len % 2) { - fifo_txrx(in, out, len); - } else { - if (in == NULL) { - memset(buf, 0xff, len); - in = buf; - } else if (out == NULL) { - out = buf; - } - dma_txrx(in, out, len); - } -#else - fifo_txrx(in, out, len); -#endif -} - -void owl_spi_irq(U8 enable) -{ -#ifdef WL_IRQ_PIN - - if (enable) - gpio_enable_pin_interrupt(WL_IRQ_PIN, GPIO_PIN_CHANGE); - else - gpio_disable_pin_interrupt(WL_IRQ_PIN); -#endif -} - -void owl_spi_cs(U8 enable) -{ - volatile avr32_spi_t *spi = &WL_SPI; - - /* - * PCS = xxx0 => NPCS[3:0] = 1110 - * PCS = xx01 => NPCS[3:0] = 1101 - * PCS = x011 => NPCS[3:0] = 1011 - * PCS = 0111 => NPCS[3:0] = 0111 - * PCS = 1111 => forbidden (no peripheral is selected) - */ - - if (enable) -#if WL_SPI_CS == 2 - spi->MR.pcs = 0x3; /* cs2 */ -#elif WL_SPI_CS == 1 - spi->MR.pcs = 0x1; /* cs1 */ -#elif WL_SPI_CS == 3 - spi->MR.pcs = 0x7; /* cs3 */ -#elif WL_SPI_CS == 0 - spi->MR.pcs = 0x0; /* cs0 */ -#endif - else - spi->MR.pcs = 0xf; -} - -void owl_spi_mdelay(uint32_t ms) -{ - volatile int a = 0; - int i; - for (i = 0; i < ms * 5000; i++) - a++; -} - -__attribute__((__interrupt__)) void avr32_irq_handler(void) -{ -#ifndef WITH_NO_DMA - volatile avr32_pdca_channel_t *pdca_tx = &AVR32_PDCA.channel[0]; - volatile avr32_pdca_channel_t *pdca_rx = &AVR32_PDCA.channel[1]; - - /* tx xfer complete */ - if (pdca_tx->IMR.trc && pdca_tx->ISR.trc) { - pdca_tx->IDR.trc = 1; - pdca_tx->CR.tdis = 1; /* disable tx xfer */ - } - - /* rx xfer complete */ - if (pdca_rx->IMR.trc && pdca_rx->ISR.trc) { - pdca_rx->IDR.trc = 1; - pdca_rx->CR.tdis = 1; /* disable rx xfer */ - } -#endif - -#ifdef WL_IRQ_PIN - if (gpio_get_pin_interrupt_flag(WL_IRQ_PIN)) { - gpio_clear_pin_interrupt_flag(WL_IRQ_PIN); - wl_spi_irq(); - } -#endif - -} |