/**
 * \file
 *
 * \brief Chip-specific DMA Controller Definitions
 *
 * - Compiler:           IAR EWAVR32 and GNU GCC for AVR32
 * - Supported devices:  AT32UC3A3
 * - AppNote:
 *
 * \author               Atmel Corporation: http://www.atmel.com \n
 *                       Support and FAQ: http://support.atmel.no/
 *
 * \page License
 *
 * 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 Atmel may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 *
 * 4. This software may only be redistributed and used in connection with an
 * Atmel AVR product.
 *
 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 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.
 */
#ifndef CHIP_DMA_CONTROLLER_H_INCLUDED
#define CHIP_DMA_CONTROLLER_H_INCLUDED

#include <chip/memory-map.h>
#include <dmac/dmaca.h>
#include <dmac/pdca.h>

/**
 * \brief DMA Controller Peripheral Identifiers
 */
enum dmac_periph_id {
	/* DMACA Peripheral IDs */
	DMAC_PERIPH_AES_RX	= 0x00,	//!< AES Result Data
	DMAC_PERIPH_AES_TX,		//!< AES Source Data
	DMAC_PERIPH_MCI_RX,		//!< MMC Read Data
	DMAC_PERIPH_MCI_TX,		//!< MMC Write Data
	DMAC_PERIPH_MSI_RX,		//!< Memory Stick Read Data
	DMAC_PERIPH_MSI_TX,		//!< Memory Stick Write Data
	DMAC_PERIPH_EXT0,		//!< External DMA Interface 0
	DMAC_PERPIH_EXT1,		//!< External DMA Interface 1

	/* PDCA Peripheral IDs */
	DMAC_PERIPH_ADC_RX	= 0x20,	//!< A/D Converter Data
	DMAC_PERIPH_SSC_RX,		//!< SSC Received Data
	DMAC_PERIPH_USART0_RX,		//!< USART0 Received Data
	DMAC_PERIPH_USART1_RX,		//!< USART1 Received Data
	DMAC_PERIPH_USART2_RX,		//!< USART2 Received Data
	DMAC_PERIPH_USART3_RX,		//!< USART3 Received Data
	DMAC_PERIPH_TWIM0_RX,		//!< TWI Master 0 Received Data
	DMAC_PERIPH_TWIM1_RX,		//!< TWI Master 1 Received Data
	DMAC_PERIPH_TWIS0_RX,		//!< TWI Slave 0 Received Data
	DMAC_PERIPH_TWIS1_RX,		//!< TWI Slave 1 Received Data
	DMAC_PERIPH_SPI0_RX,		//!< SPI0 Received Data
	DMAC_PERIPH_SPI1_RX,		//!< SPI1 Received Data
	DMAC_PERIPH_SSC_TX,		//!< SSC Data for Transmission
	DMAC_PERIPH_USART0_TX,		//!< USART0 Data for Transmission
	DMAC_PERIPH_USART1_TX,		//!< USART1 Data for Transmission
	DMAC_PERIPH_USART2_TX,		//!< USART2 Data for Transmission
	DMAC_PERIPH_USART3_TX,		//!< USART3 Data for Transmission
	DMAC_PERIPH_TWIM0_TX,		//!< TWI Master 0 Data for Transmission
	DMAC_PERIPH_TWIM1_TX,		//!< TWI Master 1 Data for Transmission
	DMAC_PERIPH_TWIS0_TX,		//!< TWI Slave 0 Data for Transmission
	DMAC_PERIPH_TWIS1_TX,		//!< TWI Slave 1 Data for Transmission
	DMAC_PERIPH_SPI0_TX,		//!< SPI0 Data for Transmission
	DMAC_PERIPH_SPI1_TX,		//!< SPI1 Data for Transmission
	DMAC_PERIPH_DAC_TX,		//!< D/A Converter Output Data

	/* Dummy ID indicating "no peripheral" */
	DMAC_PERIPH_NONE	= 0xff,	//!< No Peripheral
};

static inline unsigned int dmaca_get_periph_id(enum dmac_periph_id dmac_id)
{
	return dmac_id;
}

static inline unsigned int pdca_get_periph_id(enum dmac_periph_id dmac_id)
{
	return dmac_id - 0x20;
}

/* FIXME: Missing from the documentation */
#define CHIP_DMACA_NR_CHANNELS		4
#define CHIP_PDCA_NR_CHANNELS		8

#define PDCA_NR_PERIPH_IDS		24

static inline struct dmac_channel *dmac_aes_alloc_tx_channel(void)
{
	return dmaca_alloc_channel(&dmaca_controller, DMAC_PERIPH_NONE,
			DMAC_PERIPH_AES_TX, 0, AES_BASE + 0x40);
}

static inline struct dmac_channel *dmac_aes_alloc_rx_channel(void)
{
	return dmaca_alloc_channel(&dmaca_controller, DMAC_PERIPH_AES_RX,
			DMAC_PERIPH_NONE, AES_BASE + 0x50, 0);
}

static inline void dmac_aes_free_channel(struct dmac_channel *chan)
{
	dmaca_free_channel(&dmaca_controller, chan);
}

static inline struct dmac_channel *dmac_mci_alloc_channel(void)
{
	return dmaca_alloc_channel(&dmaca_controller, DMAC_PERIPH_MCI_RX,
			DMAC_PERIPH_MCI_TX, MCI_BASE + 0x30, MCI_BASE + 0x34);
}

static inline void dmac_mci_free_channel(struct dmac_channel *chan)
{
	dmaca_free_channel(&dmaca_controller, chan);
}

extern struct dma_controller pdca_controller;

static inline struct dmac_channel *dmac_spi_alloc_tx_channel(
		unsigned int id)
{
	assert(id <= 1);

	switch (id) {
	case 0:
		return pdca_alloc_channel(&pdca_controller, DMAC_PERIPH_NONE,
				DMAC_PERIPH_SPI0_TX, 0, SPI0_BASE + 0x0C);
	case 1:
		return pdca_alloc_channel(&pdca_controller, DMAC_PERIPH_NONE,
				DMAC_PERIPH_SPI1_TX, 0, SPI1_BASE + 0x0C);
	default:
		return NULL;
	}
}

static inline struct dmac_channel *dmac_spi_alloc_rx_channel(
		unsigned int id)
{
	assert(id <= 1);

	switch (id) {
	case 0:
		return pdca_alloc_channel(&pdca_controller,
				DMAC_PERIPH_SPI0_RX, DMAC_PERIPH_NONE,
				SPI0_BASE + 0x08, 0);
	case 1:
		return pdca_alloc_channel(&pdca_controller,
				DMAC_PERIPH_SPI1_RX, DMAC_PERIPH_NONE,
				SPI1_BASE + 0x08, 0);
	default:
		return NULL;
	}
}

static inline void dmac_spi_free_channel(struct dmac_channel *chan)
{
	pdca_free_channel(&pdca_controller, chan);
}

#endif /* CHIP_DMA_CONTROLLER_H_INCLUDED */
