generic-poky/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-pch-dma.patch

4134 lines
123 KiB
Diff

---
drivers/dma/Kconfig | 9
drivers/dma/Makefile | 1
drivers/dma/pch_dma/Makefile | 5
drivers/dma/pch_dma/pch_common.h | 146 ++++
drivers/dma/pch_dma/pch_debug.h | 60 +
drivers/dma/pch_dma/pch_dma_hal.c | 1203 +++++++++++++++++++++++++++++++++++++
drivers/dma/pch_dma/pch_dma_hal.h | 594 ++++++++++++++++++
drivers/dma/pch_dma/pch_dma_main.c | 1026 +++++++++++++++++++++++++++++++
drivers/dma/pch_dma/pch_dma_main.h | 264 ++++++++
drivers/dma/pch_dma/pch_dma_pci.c | 694 +++++++++++++++++++++
drivers/dma/pch_dma/pch_dma_pci.h | 74 ++
11 files changed, 4076 insertions(+)
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -51,6 +51,15 @@ config LNW_DMA_DEBUG
help
Enable logging in the LNW DMA drivers
+config PCH_UART_DMA
+ tristate "PCH DMA Controller"
+ depends on PCI && SERIAL_8250_PCH_DMA
+ select DMA_ENGINE
+ default y
+ help
+ This value must equal to SERIAL_8250_PCH. This config PCH_UART_DMA is
+ referred by PCH UART.
+
config INTEL_IOATDMA
tristate "Intel I/OAT DMA support"
depends on PCI && X86
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -14,4 +14,5 @@ obj-$(CONFIG_TXX9_DMAC) += txx9dmac.o
obj-$(CONFIG_SH_DMAE) += shdma.o
obj-$(CONFIG_COH901318) += coh901318.o coh901318_lli.o
obj-$(CONFIG_AMCC_PPC440SPE_ADMA) += ppc4xx/
+obj-$(CONFIG_PCH_UART_DMA) += pch_dma/
obj-$(CONFIG_TIMB_DMA) += timb_dma.o
--- /dev/null
+++ b/drivers/dma/pch_dma/Makefile
@@ -0,0 +1,5 @@
+#enable for debug;this can be added in Kconfig
+#EXTRA_CFLAGS += -DDEBUG
+
+obj-$(CONFIG_PCH_UART_DMA) += pch_dma.o
+pch_dma-objs := pch_dma_pci.o pch_dma_hal.o pch_dma_main.o
--- /dev/null
+++ b/drivers/dma/pch_dma/pch_common.h
@@ -0,0 +1,146 @@
+/*!
+ * @file ioh_common.h
+ * @brief Provides the macro definitions used by all files.
+ * @version 1.0.0.0
+ * @section
+ * 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; version 2 of the License.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * History:
+ * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD.
+ * All rights reserved.
+ *
+ * created:
+ * WIPRO 03/07/2009
+ * modified:
+ * WIPRO 05/08/2009
+ *
+ */
+
+#ifndef __IOH_COMMON_H__
+#define __IOH_COMMON_H__
+
+/*! @ingroup Global
+@def IOH_WRITE8
+@brief Macro for writing 8 bit data to an io/mem address
+*/
+#define IOH_WRITE8(val, addr) iowrite8((val), (void __iomem *)(addr))
+/*! @ingroup Global
+@def IOH_LOG
+@brief Macro for writing 16 bit data to an io/mem address
+*/
+#define IOH_WRITE16(val, addr) iowrite16((val), (void __iomem *)(addr))
+/*! @ingroup Global
+@def IOH_LOG
+@brief Macro for writing 32 bit data to an io/mem address
+*/
+#define IOH_WRITE32(val, addr) iowrite32((val), (void __iomem *)(addr))
+
+/*! @ingroup Global
+@def IOH_READ8
+@brief Macro for reading 8 bit data from an io/mem address
+*/
+#define IOH_READ8(addr) ioread8((void __iomem *)(addr))
+/*! @ingroup Global
+@def IOH_READ16
+@brief Macro for reading 16 bit data from an io/mem address
+*/
+#define IOH_READ16(addr) ioread16((void __iomem *)(addr))
+/*! @ingroup Global
+@def IOH_READ32
+@brief Macro for reading 32 bit data from an io/mem address
+*/
+#define IOH_READ32(addr) ioread32((void __iomem *)(addr))
+/*! @ingroup Global
+@def IOH_WRITE32_F
+@brief Macro for writing 32 bit data to an io/mem address
+*/
+#define IOH_WRITE32_F(val, addr) do \
+ { IOH_WRITE32((val), (addr)); (void)IOH_READ32((addr)); } while (0);
+
+/*! @ingroup Global
+@def IOH_WRITE_BYTE
+@brief Macro for writing 1 byte data to an io/mem address
+*/
+#define IOH_WRITE_BYTE IOH_WRITE8
+/*! @ingroup Global
+@def IOH_WRITE_WORD
+@brief Macro for writing 1 word data to an io/mem address
+*/
+#define IOH_WRITE_WORD IOH_WRITE16
+/*! @ingroup Global
+@def IOH_WRITE_LONG
+@brief Macro for writing long data to an io/mem address
+*/
+#define IOH_WRITE_LONG IOH_WRITE32
+
+/*! @ingroup Global
+@def IOH_READ_BYTE
+@brief Macro for reading 1 byte data from an io/mem address
+*/
+#define IOH_READ_BYTE IOH_READ8
+/*! @ingroup Global
+@def IOH_READ_WORD
+@brief Macro for reading 1 word data from an io/mem address
+*/
+#define IOH_READ_WORD IOH_READ16
+/*! @ingroup Global
+@def IOH_READ_LONG
+@brief Macro for reading long data from an io/mem address
+*/
+#define IOH_READ_LONG IOH_READ32
+
+/* Bit Manipulation Macros */
+
+/*! @ingroup Global
+@def IOH_READ_LONG
+@brief macro to set a specified bit(mask) at the
+ specified address
+*/
+#define IOH_SET_ADDR_BIT(addr, bitmask) IOH_WRITE_LONG((IOH_READ_LONG(addr) |\
+ (bitmask)), (addr))
+
+/*! @ingroup Global
+@def IOH_READ_LONG
+@brief macro to clear a specified bit(mask) at the specified address
+*/
+#define IOH_CLR_ADDR_BIT(addr, bitmask) IOH_WRITE_LONG((IOH_READ_LONG(addr) &\
+ ~(bitmask)), (addr))
+
+/*! @ingroup Global
+@def IOH_READ_LONG
+@brief macro to set a specified bitmask for a variable
+*/
+#define IOH_SET_BITMSK(var, bitmask) ((var) |= (bitmask))
+
+/*! @ingroup Global
+@def IOH_READ_LONG
+@brief macro to clear a specified bitmask for a variable
+*/
+#define IOH_CLR_BITMSK(var, bitmask) ((var) &= (~(bitmask)))
+
+/*! @ingroup Global
+@def IOH_READ_LONG
+@brief macro to set a specified bit for a variable
+*/
+#define IOH_SET_BIT(var, bit) ((var) |= (1<<(bit)))
+
+/*! @ingroup Global
+@def IOH_READ_LONG
+@brief macro to clear a specified bit for a variable
+*/
+#define IOH_CLR_BIT(var, bit) ((var) &= ~(1<<(bit)))
+
+#endif
--- /dev/null
+++ b/drivers/dma/pch_dma/pch_debug.h
@@ -0,0 +1,60 @@
+/*!
+ * @file ioh_debug.h
+ * @brief Provides the macro definitions used for debugging.
+ * @version 1.0.0.0
+ * @section
+ * 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; version 2 of the License.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * History:
+ * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD.
+ * All rights reserved.
+ *
+ * created:
+ * WIPRO 03/07/2009
+ * modified:
+ * WIPRO 05/08/2009
+ *
+ */
+
+#ifndef __IOH_DEBUG_H__
+#define __IOH_DEBUG_H__
+
+#ifdef MODULE
+#define IOH_LOG(level, fmt, args...) printk(level "%s:" fmt "\n",\
+ THIS_MODULE->name, ##args)
+#else
+#define IOH_LOG(level, fmt, args...) printk(level "%s:" fmt "\n" ,\
+ __FILE__, ##args)
+#endif
+
+
+#ifdef DEBUG
+ #define IOH_DEBUG(fmt, args...) IOH_LOG(KERN_DEBUG, fmt, ##args)
+#else
+ #define IOH_DEBUG(fmt, args...)
+#endif
+
+#ifdef IOH_TRACE_ENABLED
+ #define IOH_TRACE IOH_DEBUG
+#else
+ #define IOH_TRACE(fmt, args...)
+#endif
+
+#define IOH_TRACE_ENTER IOH_TRACE("Enter %s", __func__)
+#define IOH_TRACE_EXIT IOH_TRACE("Exit %s", __func__)
+
+
+#endif
--- /dev/null
+++ b/drivers/dma/pch_dma/pch_dma_hal.c
@@ -0,0 +1,1203 @@
+/**
+ * @file ioh_dma_hal.c
+ *
+ * @brief
+ * This file defines the IOH_DMA_CONTROLLER HAL API functions.
+ *
+ * @version 0.90
+ * @section
+ * 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; version 2 of the License.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * <hr>
+ */
+
+/*
+ * History:
+ * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD.
+ * All rights reserved.
+ *
+ * created:
+ * WIPRO 03/07/2009
+ * modified:
+ * WIPRO 08/14/2009
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/string.h>
+#include <linux/module.h>
+
+#include "pch_common.h"
+#include "pch_debug.h"
+#include "pch_dma_hal.h"
+
+/*! @ingroup HALLayer
+ @def IOH_DMA_BIT_SET
+ @brief Macro for setting selected bits of a register.
+ @remarks This macro is used to set the selected bits
+ at a given 32 bit location. Normally it is
+ used to set the bits of given register.
+*/
+#define IOH_DMA_BIT_SET(reg, bitmask) \
+ IOH_WRITE_LONG(((IOH_READ_LONG((reg)) | bitmask)), (reg))
+
+/*! @ingroup HALLayer
+ @def IOH_DMA_BIT_CLEAR
+ @brief Macro for re-setting selected bits of a register.
+ @remarks This macro is used to reset the selected bits
+ at a given 32 bit location. Normally it is
+ used to reset the bits of given register.
+*/
+#define IOH_DMA_BIT_CLEAR(regAddr, bitMask) \
+ IOH_WRITE_LONG((IOH_READ_LONG((regAddr)) & (~(bitMask))), \
+ (regAddr))
+
+/*! @ingroup HALLayer
+ @def DEFAULT_CONTROL_REGISTER_VALUE
+ @brief Macro for setting selected bits of control register.
+ @remarks This macro is used to set the mode and direction
+ bit of the control register of a specific
+ channel without affecting the settings of other
+ channels.
+*/
+#define DEFAULT_CONTROL_REGISTER_VALUE (0x33333333)
+
+/*! @ingroup HALLayer
+ @def dma_clear_interrupt_status
+ @brief Macro for clearing the interrupt status of the
+ DMA.
+ @remarks This macro is used to clear the interrupt status
+ bits of the DMA during handling of interrupts.
+*/
+#define dma_clear_interrupt_status(addr, stat0, stat2) \
+do { \
+ IOH_WRITE_LONG((stat0), ((addr) + DMA_STS0_OFFSET)); \
+ IOH_WRITE_LONG((stat2), ((addr) + DMA_STS2_OFFSET)); \
+} while (0)
+
+/*! @ingroup HALLayer
+ @def dma_get_interrupt_status
+ @brief Macro for getting the interrupt status of a
+ specific channel
+ @remarks This macro is used to get the interrupt status
+ of the DMA during handling of interrupts.
+*/
+#define dma_get_interrupt_status(ch, stat0, stat2) \
+( \
+ ((ch) < 8) ? \
+ (((stat0) & (DMA_INTERRUPT_OCCUR << ch)) != 0) \
+ : \
+ (((stat2) & (DMA_INTERRUPT_OCCUR << (ch - 8))) != 0) \
+)
+
+/*! @ingroup HALLayer
+ @def dma_get_abort_status
+ @brief Macro for getting the abort status of a specific
+ channel.
+ @remarks This macro is used to get the abort status
+ of the DMA during handling of interrupts.
+*/
+#define dma_get_abort_status(ch, stat0, stat2) \
+( \
+ ((ch) < 8) ? \
+ (((stat0) & (DMA_ABORT_OCCUR << ch)) != 0) \
+ : \
+ (((stat2) & (DMA_ABORT_OCCUR << (ch - 8))) != 0) \
+)
+
+/* Global Varibles */
+/*! @ingroup Global
+ @var ioh_dma_channel_info
+ @brief Retains the specific channel information.
+*/
+struct ioh_dma_controller_info ioh_dma_channel_info[IOH_DMA_CHANNELS_MAX];
+
+/* Channel Allocation Table for DMA */
+/*! @ingroup Global
+ @var ioh_dma_channel_table
+ @brief Retains the specific channel allocation
+ information.
+*/
+struct ioh_dma_channel_alloc_table ioh_dma_channel_table[IOH_DMA_CHANNELS_MAX]
+= {
+ /* 4 channel DMA device0 (Reserved for GE.) */
+ {IOH_DMA_4CH0, IOH_DMA_TX_DATA_REQ0, PCI_DEVICE_ID_IOH_SPI, 0, 0, 0, 0},
+ {IOH_DMA_4CH0, IOH_DMA_RX_DATA_REQ0, PCI_DEVICE_ID_IOH_SPI, 1, 0, 0, 0},
+ {IOH_DMA_4CH0, 0, 0, 2, 0, 0, 0},
+ {IOH_DMA_4CH0, 0, 0, 3, 0, 0, 0},
+
+ /* 4 channel DMA device1 (Not reserved.) */
+ {IOH_DMA_4CH1, 0, 0, 0, 0, 0, 0},
+ {IOH_DMA_4CH1, 0, 0, 1, 0, 0, 0},
+ {IOH_DMA_4CH1, 0, 0, 2, 0, 0, 0},
+ {IOH_DMA_4CH1, 0, 0, 3, 0, 0, 0},
+
+ /* 4 channel DMA device2 (Not reserved.) */
+ {IOH_DMA_4CH2, 0, 0, 0, 0, 0, 0},
+ {IOH_DMA_4CH2, 0, 0, 1, 0, 0, 0},
+ {IOH_DMA_4CH2, 0, 0, 2, 0, 0, 0},
+ {IOH_DMA_4CH2, 0, 0, 3, 0, 0, 0},
+
+ /* 4 channel DMA device3 (Not reserved.) */
+ {IOH_DMA_4CH3, 0, 0, 0, 0, 0, 0},
+ {IOH_DMA_4CH3, 0, 0, 1, 0, 0, 0},
+ {IOH_DMA_4CH3, 0, 0, 2, 0, 0, 0},
+ {IOH_DMA_4CH3, 0, 0, 3, 0, 0, 0},
+
+ /* 4 channel DMA device4 (Not reserved.) */
+ {IOH_DMA_4CH4, 0, 0, 0, 0, 0, 0},
+ {IOH_DMA_4CH4, 0, 0, 1, 0, 0, 0},
+ {IOH_DMA_4CH4, 0, 0, 2, 0, 0, 0},
+ {IOH_DMA_4CH4, 0, 0, 3, 0, 0, 0},
+
+ /* 8 channel DMA device0 (Reserved for GE.) */
+ {IOH_DMA_8CH0, IOH_DMA_TX_DATA_REQ0, PCI_DEVICE_ID_IOH_UART0, 0, 0, 0,
+ 0},
+ {IOH_DMA_8CH0, IOH_DMA_RX_DATA_REQ0, PCI_DEVICE_ID_IOH_UART0, 1, 0, 0,
+ 0},
+ {IOH_DMA_8CH0, IOH_DMA_TX_DATA_REQ0, PCI_DEVICE_ID_IOH_UART1, 2, 0, 0,
+ 0},
+ {IOH_DMA_8CH0, IOH_DMA_RX_DATA_REQ0, PCI_DEVICE_ID_IOH_UART1, 3, 0, 0,
+ 0},
+ {IOH_DMA_8CH0, IOH_DMA_TX_DATA_REQ0, PCI_DEVICE_ID_IOH_UART2, 4, 0, 0,
+ 0},
+ {IOH_DMA_8CH0, IOH_DMA_RX_DATA_REQ0, PCI_DEVICE_ID_IOH_UART2, 5, 0, 0,
+ 0},
+ {IOH_DMA_8CH0, IOH_DMA_TX_DATA_REQ0, PCI_DEVICE_ID_IOH_UART3, 6, 0, 0,
+ 0},
+ {IOH_DMA_8CH0, IOH_DMA_RX_DATA_REQ0, PCI_DEVICE_ID_IOH_UART3, 7, 0, 0,
+ 0},
+
+ /* 8 channel DMA device1 */
+ {IOH_DMA_8CH1, 0, 0, 0, 0, 0, 0},
+ {IOH_DMA_8CH1, 0, 0, 1, 0, 0, 0},
+ {IOH_DMA_8CH1, 0, 0, 2, 0, 0, 0},
+ {IOH_DMA_8CH1, 0, 0, 3, 0, 0, 0},
+ {IOH_DMA_8CH1, 0, 0, 4, 0, 0, 0},
+ {IOH_DMA_8CH1, 0, 0, 5, 0, 0, 0},
+ {IOH_DMA_8CH1, 0, 0, 6, 0, 0, 0},
+ {IOH_DMA_8CH1, 0, 0, 7, 0, 0, 0},
+
+ /* 8 channel DMA device2 */
+ {IOH_DMA_8CH2, 0, 0, 0, 0, 0, 0},
+ {IOH_DMA_8CH2, 0, 0, 1, 0, 0, 0},
+ {IOH_DMA_8CH2, 0, 0, 2, 0, 0, 0},
+ {IOH_DMA_8CH2, 0, 0, 3, 0, 0, 0},
+ {IOH_DMA_8CH2, 0, 0, 4, 0, 0, 0},
+ {IOH_DMA_8CH2, 0, 0, 5, 0, 0, 0},
+ {IOH_DMA_8CH2, 0, 0, 6, 0, 0, 0},
+ {IOH_DMA_8CH2, 0, 0, 7, 0, 0, 0},
+
+ /* 8 channel DMA device3 (Doubts in allocating.) */
+ {IOH_DMA_8CH3, 0, 0, 0, 0, 0, 0},
+ {IOH_DMA_8CH3, 0, 0, 1, 0, 0, 0},
+ {IOH_DMA_8CH3, 0, 0, 2, 0, 0, 0},
+ {IOH_DMA_8CH3, 0, 0, 3, 0, 0, 0},
+ {IOH_DMA_8CH3, 0, 0, 4, 0, 0, 0},
+ {IOH_DMA_8CH3, 0, 0, 5, 0, 0, 0},
+ {IOH_DMA_8CH3, 0, 0, 6, 0, 0, 0},
+ {IOH_DMA_8CH3, 0, 0, 7, 0, 0, 0},
+
+ /* 12 channel DMA device0 */
+ {IOH_DMA_12CH0, 0, 0, 0, 0, 0, 0},
+ {IOH_DMA_12CH0, 0, 0, 1, 0, 0, 0},
+ {IOH_DMA_12CH0, 0, 0, 2, 0, 0, 0},
+ {IOH_DMA_12CH0, 0, 0, 3, 0, 0, 0},
+ {IOH_DMA_12CH0, 0, 0, 4, 0, 0, 0},
+ {IOH_DMA_12CH0, 0, 0, 5, 0, 0, 0},
+ {IOH_DMA_12CH0, 0, 0, 6, 0, 0, 0},
+ {IOH_DMA_12CH0, 0, 0, 7, 0, 0, 0},
+ {IOH_DMA_12CH0, 0, 0, 8, 0, 0, 0},
+ {IOH_DMA_12CH0, 0, 0, 9, 0, 0, 0},
+ {IOH_DMA_12CH0, 0, 0, 10, 0, 0, 0},
+ {IOH_DMA_12CH0, 0, 0, 11, 0, 0, 0}
+};
+
+/* Function Definitions */
+
+/*! @ingroup HALLayerAPI
+ @fn void __init dma_init(u32 base, u32 dev_type)
+ @brief Initializes local data structures for the DMAC device.
+ @remarks This function is called when a DMA device is detected.
+ It initializes the data structures associated
+ with the obtained device. The main tasks
+ performed by this function are:
+ - Waits until the status of a DMA channel
+ becomes idle and then disables it.
+ - Initializes the data structures that can
+ be used further.
+
+ @param base [@ref IN] The base address.
+ @param dev_type [@ref IN] The type of the device.
+
+ @return None.
+
+ @see
+ - ioh_dma_probe
+ */
+
+void __init dma_init(u32 base, u32 dev_type)
+{
+ int i;
+ u32 counter;
+ u16 DMAStatus;
+
+ for (i = 0; i < IOH_DMA_CHANNELS_MAX; i++) {
+ if (ioh_dma_channel_table[i].dma_dev_id == dev_type) {
+ counter = COUNTER_LIMIT;
+
+ ioh_dma_channel_table[i].ch_found = 1;
+ ioh_dma_channel_table[i].ch_alloced = 0;
+ ioh_dma_channel_table[i].base = base;
+
+ do {
+ get_dma_status(i, &DMAStatus);
+ } while ((counter--) && (DMAStatus != DMA_STATUS_IDLE));
+
+ (void)dma_disable_ch(i);
+ IOH_DEBUG("dma_init -> Channel %d disabled.\n", i);
+
+ (void)dma_enable_disable_interrupt
+ (i, IOH_DMA_INTERRUPT_DISABLE);
+ IOH_DEBUG
+ ("dma_init -> Interrupt disabled for channel %d.\n",
+ i);
+ }
+ }
+
+ IOH_DEBUG("Function dma_init invoked successfully.\n");
+}
+
+/*! @ingroup HALLayerAPI
+ @fn void dma_exit(u32 dev_type)
+ @brief De-initializes the DMA device.
+ @remarks The main tasks performed by this function are:
+ - Waits for a small interval for each channel
+ if the channel is not idle so that it can
+ complete its transfer.
+ - Disables the channel.
+ - Disables the concerned interrupt.
+
+ @param dev_type [@ref IN] The type of the device.
+
+ @return None
+
+ @see
+ - ioh_dma_remove
+ - ioh_dma_suspend
+*/
+void dma_exit(u32 dev_type)
+{
+ int i;
+ u32 counter;
+ u16 DMAStatus;
+
+ for (i = 0; i < IOH_DMA_CHANNELS_MAX; i++) {
+ if (ioh_dma_channel_table[i].dma_dev_id == dev_type &&
+ ioh_dma_channel_table[i].ch_found == 1) {
+ counter = COUNTER_LIMIT;
+ get_dma_status(i, &DMAStatus);
+
+ while ((counter > 0) &&
+ (DMAStatus != DMA_STATUS_IDLE)) {
+ counter--;
+ get_dma_status(i, &DMAStatus);
+ }
+
+ (void)dma_disable_ch(i);
+ IOH_DEBUG("dma_exit -> Channel %d disabled.\n", i);
+
+ (void)dma_enable_disable_interrupt
+ (i, IOH_DMA_INTERRUPT_DISABLE);
+ IOH_DEBUG("dma_exit -> Interrupt disabled for channel "
+ "%d.\n", i);
+ }
+ }
+
+ IOH_DEBUG("Function dma_exit invoked successfully.\n");
+}
+
+/*! @ingroup HALLayerAPI
+ @fn int dma_set_mode(int channel,
+ struct ioh_dma_mode_param stModeParam)
+ @brief Sets the Mode of transfer for DMA.
+ @remarks Does the setting of direction of transfer, access size
+ type and transfer mode. This function does not
+ perform any register write. The main tasks
+ performed by this function are:
+ - Set the DMATransferDirection field of @ref
+ ioh_dma_channel_info with the direction of
+ transfer specified.
+ - Set the DMAAccessSize field of @ref
+ ioh_dma_channel_info with the Access Size Type
+ specified.
+ - Set the DMATransferMode field of @ref
+ ioh_dma_channel_info structure with the DMA mode
+ specified.
+
+ @param channel [@ref IN] The channel for which mode is to be set.
+ @param stModeParam [@ref IN] Structure which contains the
+ parameters for the setting of Mode.
+
+ @return int
+ - @ref IOH_DMA_SUCCESS --> On success.
+
+ @see
+ - ioh_set_dma_mode
+ */
+int dma_set_mode(int channel, struct ioh_dma_mode_param stModeParam)
+{
+ ioh_dma_channel_info[channel].DMAAccessSize = stModeParam.DMASizeType;
+ ioh_dma_channel_info[channel].DMATransferMode =
+ stModeParam.DMATransferMode;
+ ioh_dma_channel_info[channel].DMATransferDirection =
+ stModeParam.TransferDirection;
+
+ IOH_DEBUG("Function dma_set_mode returns %d.\n", IOH_DMA_SUCCESS);
+ return IOH_DMA_SUCCESS;
+}
+
+/*! @ingroup HALLayerAPI
+ @fn int dma_set_addr(int channel, u32 iaddr, u32 oaddr)
+ @brief Sets the Inside and Outside address in the case
+ of ONE SHOT MODE
+ @remarks This function updates Inside address and outside
+ address to be set in ONE SHOT mode. The main
+ tasks performed by this function are:
+ - Set the field in_addr of the @ref
+ ioh_dma_channel_info structure of the
+ corresponding channel to the value of the
+ argument iaddr.
+ - Set the field out_addr of the @ref
+ ioh_dma_channle_info structure of the
+ corresponding channel to the value of the
+ argument oaddr.
+
+ @param channel [@ref IN] Channel for which addresses is
+ to be set.
+ @param iaddr [@ref IN] Inside address to be set
+ @param oaddr [@ref IN] Outside address to be set
+
+ @return int
+ - @ref IOH_DMA_SUCCESS --> On Success.
+
+ @see
+ - ioh_set_dma_addr
+
+ */
+int dma_set_addr(int channel, u32 iaddr, u32 oaddr)
+{
+ ioh_dma_channel_info[channel].in_addr = iaddr;
+ ioh_dma_channel_info[channel].out_addr = oaddr;
+
+ IOH_DEBUG("Function dma_set_addr returns %d.\n", IOH_DMA_SUCCESS);
+ return IOH_DMA_SUCCESS;
+}
+
+/*! @ingroup HALLayerAPI
+ @fn int dma_enable_ch(int channel)
+ @brief Enables the DMA channel specified.
+ @remarks This function sets the entire DMA settings such as
+ the transfer direction, transfer mode and
+ enables the channel. The main tasks performed by
+ this function are:
+ - Sets the transfer direction.
+ - Sets the transfer mode.
+ - Enabling the channel.
+
+ @param channel [@ref IN] Channel number that
+ is to be enabled.
+
+ @return int
+ - @ref IOH_DMA_SUCCESS --> On success.
+
+ @see
+ - ioh_enable_dma
+ */
+int dma_enable_ch(int channel)
+{
+ u32 base_address;
+ u16 transfer_mode;
+ u32 ctl0;
+ u32 ctrl_val = DEFAULT_CONTROL_REGISTER_VALUE;
+ int ch;
+
+ /* Marking the channel as enabled. */
+ ioh_dma_channel_info[channel].bChEnabled = 1;
+
+ ch = ioh_dma_channel_table[channel].channel;
+ base_address = ioh_dma_channel_table[channel].base;
+
+ ctl0 = 0;
+
+ /* Setting of transfer direction. */
+ if (ioh_dma_channel_info[channel].DMATransferDirection ==
+ IOH_DMA_DIR_OUT_TO_IN) {
+ ctl0 |= IOH_DMA_DIR_OUT_TO_IN;
+ }
+
+ /* Setting the transfer mode features. */
+ transfer_mode = ioh_dma_channel_info[channel].DMATransferMode;
+
+ /* If scatter gather mode. */
+ if (transfer_mode == DMA_SCATTER_GATHER_MODE) {
+ u32 next_desc;
+
+ next_desc = ((u32) ioh_dma_channel_info[channel].pHeadOfList);
+ IOH_WRITE_LONG(next_desc, (base_address + (DMA_NX_AD_OFFSET +
+ (ch * 0x10))));
+
+ ctl0 |= DMA_SCATTER_GATHER_MODE;
+ }
+ /* If one shot mode. */
+ else {
+ u32 in_address = ioh_dma_channel_info[channel].in_addr;
+ u32 out_address = ioh_dma_channel_info[channel].out_addr;
+ u32 access_size = ioh_dma_channel_info[channel].DMAAccessSize;
+ u32 count = ioh_dma_channel_info[channel].DMATransferSize;
+
+ ctl0 |= DMA_ONE_SHOT_MODE;
+
+ count |= access_size;
+
+ IOH_WRITE_LONG(in_address,
+ (base_address +
+ (DMA_IN_AD_OFFSET + (ch * 0x10))));
+ IOH_WRITE_LONG(out_address,
+ (base_address +
+ (DMA_OUT_AD_OFFSET + (ch * 0x10))));
+ IOH_WRITE_LONG(count,
+ (base_address + (DMA_SZ_OFFSET + (ch * 0x10))));
+ }
+
+ /* Enabling the interrupts. */
+ (void)dma_enable_disable_interrupt(channel, IOH_DMA_INTERRUPT_ENABLE);
+
+ /* Updating Control register. */
+ if (ch < 8) {
+ /* Clearing the three bits corresponding
+ to the mode and transfer direction of
+ specific channel.
+ */
+ ctrl_val &= ~((MSK_ALL_THREE) << (ch * DMA_SHIFT_MODE_BITS));
+
+ /* Setting the transfer mode and direction. */
+ ctrl_val |= (ctl0 << (ch * DMA_SHIFT_MODE_BITS));
+
+ /* Updating to the register. */
+ IOH_WRITE_LONG(ctrl_val, (base_address + DMA_CTL0_OFFSET));
+
+ IOH_DEBUG("dma_enable -> Control register(0) value: "
+ "%x.\n",
+ IOH_READ_LONG((base_address + DMA_CTL0_OFFSET)));
+ } else {
+ /* Clearing the three bits corresponding
+ to the mode and transfer direction of
+ specific channel.
+ */
+ ctrl_val &=
+ ~((MSK_ALL_THREE) << ((ch - 8) * DMA_SHIFT_MODE_BITS));
+
+ /* Setting the transfer mode and direction. */
+ ctrl_val |= (ctl0 << ((ch - 8) * DMA_SHIFT_MODE_BITS));
+
+ /* Updating to the register. */
+ IOH_WRITE_LONG(ctrl_val, (base_address + DMA_CTL3_OFFSET));
+
+ IOH_DEBUG("dma_enable -> Control register(3) value: "
+ "%x.\n",
+ IOH_READ_LONG((base_address + DMA_CTL3_OFFSET)));
+ }
+
+ IOH_DEBUG("Function dma_enable_ch returns %d.\n", IOH_DMA_SUCCESS);
+ return IOH_DMA_SUCCESS;
+}
+
+/*! @ingroup HALLayerAPI
+ @fn int dma_disable_ch(int channel)
+ @brief Disables the DMA channel specified.
+ @remarks This function performs the necessary
+ register updation in-order to disable
+ the DMA channel.
+
+ @param channel [@ref IN] Channel to be disabled.
+
+ @return int
+ - @ref IOH_DMA_SUCCESS
+
+ @see
+ - ioh_disable_dma
+ */
+int dma_disable_ch(int channel)
+{
+ u32 base_address;
+ u16 ch;
+
+ ch = ioh_dma_channel_table[channel].channel;
+ base_address = ioh_dma_channel_table[channel].base;
+
+ if (channel < 8) {
+ /* Clearing the mode bits of the channel */
+ IOH_DMA_BIT_CLEAR((base_address + DMA_CTL0_OFFSET),
+ (DMA_MASK_MODE_BITS <<
+ (ch * DMA_SHIFT_MODE_BITS)));
+ } else {
+ /* Clearing the mode bits of the channel */
+ IOH_DMA_BIT_CLEAR((base_address + DMA_CTL3_OFFSET),
+ (DMA_MASK_MODE_BITS <<
+ ((ch - 8) * DMA_SHIFT_MODE_BITS)));
+ }
+
+ /* Updating the enable variable. */
+ ioh_dma_channel_info[channel].bChEnabled = (u16) 0;
+
+ IOH_DEBUG("Function dma_disable_ch returns " "%d.\n", IOH_DMA_SUCCESS);
+ return IOH_DMA_SUCCESS;
+}
+
+/*! @ingroup HALLayerAPI
+ @fn int dma_set_count (int channel, u32 count)
+ @brief Sets the count value .
+ @remarks Updates the transfer size for ONE_SHOT_MODE
+ of DMA Transfer. The main tasks performed by
+ this function are:
+ - Set the DMATransferSize field of the
+ @ref ioh_dma_channel_info structure to the
+ value of the argument count.
+
+ @param channel [@ref IN] Channel number for
+ which value is to be set
+ @param count [@ref IN] Transfer Size value.
+
+ @return int
+ - @ref IOH_DMA_SUCCESS
+
+ @see
+ - ioh_set_dma_count
+ */
+int dma_set_count(int channel, u32 count)
+{
+ ioh_dma_channel_info[channel].DMATransferSize = count;
+
+ IOH_DEBUG("Function dma_set_count returns %d.\n", IOH_DMA_SUCCESS);
+ return IOH_DMA_SUCCESS;
+}
+
+/*! @ingroup HALLayerAPI
+ @fn int dma_add_desc(int channel,
+ struct ioh_dma_desc *start,
+ struct ioh_dma_desc *end)
+ @brief Adds descriptors to the existing list of descriptors.
+ @remarks This function accepts the descriptor list and appends
+ it to the existing list of descriptors. The main
+ tasks performed by this function are:
+ - Obtains the virtual address of the end of the
+ currently set descriptor list. If it is not
+ successful returns with an error.
+ - Appends the value of the argument start to the
+ nextDesc field of the descriptor pointed by the
+ pTailOfList field of the
+ @ref ioh_dma_channel_info structure with the
+ value of the argument start after appropriately
+ setting the last two bits to denote
+ Follow_Next_Descriptor_Without_Interrupt.
+ - Updates the value of the argument end to the
+ pTailOfList field of the @ref
+ ioh_dma_channel_info structure for the
+ corresponding channel.
+
+ @param channel [@ref IN] Channel number.
+ @param start [@ref IN] Reference to first
+ descriptor of list.
+ @param end [@ref IN] Reference to last
+ descriptor of list.
+
+ @return int
+ - @ref IOH_DMA_SUCCESS --> If appending of the
+ descriptor is successful.
+
+ @see
+ - ioh_add_dma_desc
+*/
+int dma_add_desc(int channel, struct ioh_dma_desc *start,
+ struct ioh_dma_desc *end)
+{
+ struct ioh_dma_desc *desc_addr;
+
+ desc_addr = ioh_dma_channel_info[channel].pTailOfList;
+
+ /* Obtaining the virtual address. */
+ desc_addr = (struct ioh_dma_desc *) phys_to_virt((u32) desc_addr);
+
+ /* If virtual address calculation successful. */
+ desc_addr->nextDesc = (u32) start;
+ ioh_dma_channel_info[channel].pTailOfList = end;
+
+ IOH_DEBUG("Function dma_add_desc returns %d.\n", IOH_DMA_SUCCESS);
+ return IOH_DMA_SUCCESS;
+}
+
+/*! @ingroup HALLayerAPI
+ @fn void dma_set_callback (int channel, void (*ioh_dma_cbr)
+ ( int value,unsigned long data1),unsigned long data)
+ @brief To set callback function.
+ @remarks Sets the callback function to be called for a channel.
+ The main task performed by this function is:
+ - Updates the callback pointer for the channel
+ in the structure ioh_dma_channel_info with the
+ parameter passed.
+
+ @param channel [@ref IN] Channel number.
+ @param ioh_dma_cbr [@ref IN] Function pointer
+ to call back function.
+ @param data [@ref IN] The data to be passed to
+ the callback function during
+ invoking.
+
+ @return None.
+
+ @see
+ - ioh_dma_set_callback
+ */
+void dma_set_callback(int channel,
+ void (*ioh_dma_cbr) (int value, unsigned long data1),
+ unsigned long data)
+{
+ ioh_dma_channel_info[channel].call_back_func_ptr = ioh_dma_cbr;
+ ioh_dma_channel_info[channel].callback_data = data;
+
+ IOH_DEBUG("Function dma_set_callback invoked successfully.\n");
+}
+
+/*! @ingroup HALLayerAPI
+ @fn irqreturn_t dma_interrupt (int irq, void *dev_id)
+ @brief Interrupt handler.
+ @remarks Handles the interrupt for the DMA. The main tasks
+ performed by this function are:
+ - Checks each DMA channels whether a DMA
+ transmission end or DMA status interrupt has
+ occurred.
+ - If a transmission end interrupt has occurred,
+ then invoke the callback function with @ref
+ IOH_DMA_END, denoting that the DMA transmission
+ has end.
+ - If a DMA abort interrupt has occurred, then
+ invoke the callback function with @ref
+ IOH_DMA_ABORT, denoting that a DMA abort has
+ occurred.
+
+ @param irq [@ref IN] Interrupt Request number
+ @param dev_id [@ref IN] dev_id of device for which
+ interrupt is raised .
+
+ @return irqreturn_t
+ - IRQ_HANDLED --> If interrupt has been processed.
+ - IRQ_NONE --> If no interrupt has been processed.
+
+ */
+irqreturn_t dma_interrupt(int irq, void *dev_id)
+{
+ irqreturn_t retval = IRQ_NONE;
+ u32 status_reg0;
+ u32 status_reg2;
+ u32 base_address;
+ u32 dev_type;
+ u32 i;
+ u16 status;
+
+ base_address = ((struct ioh_dma_devices *) dev_id)->base_addr;
+ dev_type = ((struct ioh_dma_devices *) dev_id)->dev_typ;
+
+ /* Reading the status registers. */
+ status_reg0 = IOH_READ_LONG((base_address + DMA_STS0_OFFSET));
+ status_reg2 = IOH_READ_LONG((base_address + DMA_STS2_OFFSET));
+ IOH_DEBUG("dma_interrupt -> Status register STS0: %x STS2: "
+ "%x.\n", status_reg0, status_reg2);
+
+ /* Clearing the interrupts. */
+ dma_clear_interrupt_status(base_address, status_reg0, status_reg2);
+
+ /* Handling the interrupts. */
+ for (i = 0; i < IOH_DMA_CHANNELS_MAX; i++) {
+ if ((ioh_dma_channel_table[i].dma_dev_id == dev_type) &&
+ (ioh_dma_channel_table[i].ch_alloced == 1) &&
+ (ioh_dma_channel_info[i].bChEnabled == 1)
+ ) {
+ status =
+ dma_get_interrupt_status(ioh_dma_channel_table
+ [i].channel, status_reg0,
+ status_reg2);
+ IOH_DEBUG
+ ("dma_interrupt -> Interrupt status for ch: %d is "
+ "%x.\n", i, status);
+
+ if (status == 1) {
+ int value = IOH_DMA_END;
+
+ status =
+ dma_get_abort_status(ioh_dma_channel_table
+ [i].channel,
+ status_reg0,
+ status_reg2);
+
+ if (status == 1) {
+ value = IOH_DMA_ABORT;
+
+ IOH_DEBUG
+ ("dma_interrupt -> DMA Abort "
+ "interrupt from channel%d.\n", i);
+ }
+#ifdef DEBUG
+ else {
+ IOH_DEBUG
+ ("dma_interrupt -> DMA Completion "
+ "interrupt "
+ "from channel%d.\n", i);
+ }
+#endif
+ if (ioh_dma_channel_info[i].
+ call_back_func_ptr) {
+ u32 data =
+ ioh_dma_channel_info
+ [i].callback_data;
+ (ioh_dma_channel_info
+ [i].call_back_func_ptr) (value, data);
+ }
+
+ /* Determining whether the channel has been
+ disabled. */
+ {
+ u32 ctrl_val;
+ s32 ch =
+ ioh_dma_channel_table[i].channel;
+ u32 base_address =
+ ioh_dma_channel_table[i].base;
+
+ if (ch < 8) {
+ ctrl_val =
+ IOH_READ_LONG((base_address
+ + DMA_CTL0_OFFSET));
+
+ ctrl_val &=
+ ((0x3) <<
+ (ch * DMA_SHIFT_MODE_BITS));
+ } else {
+ ctrl_val =
+ IOH_READ_LONG((base_address
+ + DMA_CTL3_OFFSET));
+ ctrl_val &=
+ ((0x3) <<
+ ((ch - 8) *
+ DMA_SHIFT_MODE_BITS));
+ }
+
+ ioh_dma_channel_info[i].bChEnabled =
+ (ctrl_val != 0) ? 1 : 0;
+
+ } /* End */
+
+ retval = IRQ_HANDLED;
+ }
+ }
+ }
+
+ IOH_DEBUG("Function dma_interrupt returns %d.\n", retval);
+ return retval;
+}
+
+/*! @ingroup HALLayerAPI
+ @fn int dma_direct_start (int channel)
+ @brief To generate the DMA request which each Function-IP
+ transmits.
+ @remarks This function is used to initiate the DMA
+ transfer process. The main task performed by
+ this function is:
+ - Sets the value of DMAn Direct Start bit in the
+ Control register 2 to start DMA transfer on
+ channel n.
+
+ @param channel [@ref IN] Channel number for which DMA
+ transfer is to be started.
+
+ @return int
+ - @ref IOH_DMA_SUCCESS --> On Success.
+
+ @see
+ - ioh_dma_direct_start
+ */
+int dma_direct_start(int channel)
+{
+ int ch;
+ u32 base_address;
+
+ ch = ioh_dma_channel_table[channel].channel;
+ base_address = ioh_dma_channel_table[channel].base;
+
+ if (ch < 8) {
+ IOH_DMA_BIT_SET((base_address + DMA_CTL2_OFFSET),
+ (DMA_DIR_START << ch));
+ } else {
+ IOH_DMA_BIT_SET((base_address + DMA_CTL2_OFFSET),
+ (DMA_DIR_START << (ch + 6)));
+ }
+
+ IOH_DEBUG("dma_direct_start -> Direct2 RegValue: "
+ "%x.\n", IOH_READ_LONG((base_address + DMA_CTL2_OFFSET)));
+
+ IOH_DEBUG("Function dma_direct_start returns "
+ "%d.\n", IOH_DMA_SUCCESS);
+ return IOH_DMA_SUCCESS;
+}
+
+/*! @ingroup HALLayerAPI
+ @fn int dma_set_priority (int channel, int priority)
+ @brief Set the priority.
+ @remarks Sets the priority for a channel. The main task
+ performed by this function is:
+ - Set the value of DMAn Priority Level bits for
+ the channel in the Control register1.
+
+ @param channel [@ref IN] DMA channel number.
+ @param priority [@ref IN] Priority to be set for
+ the DMA channel.
+
+ @return int
+ - @ref IOH_DMA_SUCCESS --> On Success.
+
+ @see
+ - ioh_set_dma_priority
+ */
+int dma_set_priority(int channel, int priority)
+{
+ int ch;
+ u32 base_address;
+ u32 reg_val;
+
+ ch = ioh_dma_channel_table[channel].channel;
+ base_address = ioh_dma_channel_table[channel].base;
+
+ reg_val = IOH_READ_LONG((base_address + DMA_CTL1_OFFSET));
+
+ if (ch < 8) {
+ reg_val &=
+ ~(DMA_MASK_PRIORITY_BITS << (ch * DMA_SHIFT_PRIORITY_BITS));
+ reg_val |= (((u32) priority) << (ch * DMA_SHIFT_PRIORITY_BITS));
+ } else {
+ reg_val &=
+ ~(DMA_MASK_PRIORITY_BITS <<
+ (((ch - 8) * DMA_SHIFT_PRIORITY_BITS) + 2));
+ reg_val |=
+ (((u32) priority) <<
+ (((ch - 8) * DMA_SHIFT_PRIORITY_BITS) + 2));
+ }
+
+ IOH_WRITE_LONG(reg_val, (base_address + DMA_CTL1_OFFSET));
+
+ IOH_DEBUG("Function dma_set_priority returns "
+ "%d.\n", IOH_DMA_SUCCESS);
+ return IOH_DMA_SUCCESS;
+}
+
+/*! @ingroup HALLayerAPI
+ @fn int dma_enable_disable_interrupt (int channel, int bEnable)
+ @brief Enables or Disables Interrupts .
+ @remarks Writes the corresponding register to either
+ enable or disable interrupts. The main tasks
+ performed by this function are:
+ - If bEnable is DMA_INTERRUPT_ENABLE (1),
+ sets the DMAn Interrupt Enable bit in control
+ register2.
+ - If bEnable is DMA_INTERRUPT_DISABLE (0),
+ clears the DMAn Interrupt Enable bit in control
+ register2.
+
+ @param channel [@ref IN] Channel number
+ @param bEnable [@ref IN] Flag to indicate whether
+ to enable or disable interrupt.
+
+ @return int
+ - @ref IOH_DMA_SUCCESS --> On Success.
+
+ @see
+ - dma_init
+ - dma_exit
+ */
+int dma_enable_disable_interrupt(int channel, int bEnable)
+{
+ u32 base_address;
+ u16 ch;
+
+ ch = ioh_dma_channel_table[channel].channel;
+ base_address = ioh_dma_channel_table[channel].base;
+
+ if (ch < 8) {
+ if (IOH_DMA_INTERRUPT_ENABLE == bEnable) {
+ IOH_DMA_BIT_SET((base_address + DMA_CTL2_OFFSET),
+ (DMA_INTERRUPT_BIT << ch));
+ } else { /* if(bEnable == IOH_DMA_INTERRUPT_DISABLE) */
+
+ IOH_DMA_BIT_CLEAR((base_address + DMA_CTL2_OFFSET),
+ (DMA_INTERRUPT_BIT << ch));
+ }
+
+ } else {
+ if (IOH_DMA_INTERRUPT_ENABLE == bEnable) {
+ IOH_DMA_BIT_SET((base_address + DMA_CTL2_OFFSET),
+ (DMA_INTERRUPT_BIT << (ch + 8)));
+ } else { /* if(bEnable == IOH_DMA_INTERRUPT_DISABLE) */
+
+ IOH_DMA_BIT_CLEAR((base_address + DMA_CTL2_OFFSET),
+ (DMA_INTERRUPT_BIT << (ch + 8)));
+ }
+ }
+
+ IOH_DEBUG("dma_enable_disable_interrupt -> CTL2 Register Value: "
+ "%x.\n", IOH_READ_LONG((base_address + DMA_CTL2_OFFSET)));
+
+ IOH_DEBUG("Function dma_enable_disable_interrupt returns "
+ "%d.\n", IOH_DMA_SUCCESS);
+ return IOH_DMA_SUCCESS;
+}
+
+/*! @ingroup HALLayerAPI
+ @fn void get_dma_status(int channel, u16 *pDMAStatus)
+ @brief Gets the Status of DMA.
+ @remarks Gets the status of the specified DMA Channel. The
+ main task performed by this function is:
+ - Reads the data in the DMAn (for channel .n.)
+ Status bit of Status register0 (4ch or 8ch) or
+ Status register2 (12ch) and copy the value into
+ pDMAStatus.
+
+ @param channel [@ref IN] Channel number.
+ @param pDMAStatus [@ref INOUT] Address of variable to
+ which
+ status information is copied.
+
+ @return None.
+
+ @see
+ - dma_exit
+ - dma_init
+ - ioh_set_dma_mode
+ - ioh_set_dma_addr
+ - ioh_set_dma_count
+ - ioh_set_dma_desc
+ - ioh_add_dma_desc
+ - ioh_enable_dma
+ - ioh_disable_dma
+ - ioh_set_dma_priority
+ - ioh_dma_direct_start
+
+ */
+
+void get_dma_status(int channel, u16 *pDMAStatus)
+{
+ u32 status_val;
+ u32 base_address;
+ u16 ch;
+
+ ch = ioh_dma_channel_table[channel].channel;
+ base_address = ioh_dma_channel_table[channel].base;
+
+ if (ch < 8) {
+ status_val = IOH_READ_LONG(base_address + DMA_STS0_OFFSET);
+ *pDMAStatus = (u16) ((status_val >> (DMA_SHIFT_STATUS_BITS +
+ (ch *
+ DMA_SIZE_STATUS_BITS))) &
+ (DMA_MASK_STATUS_BITS));
+ } else {
+ status_val = IOH_READ_LONG(base_address + DMA_STS2_OFFSET);
+ *pDMAStatus = (u16) ((status_val >> (DMA_SHIFT_STATUS_BITS +
+ ((ch -
+ 8) *
+ DMA_SIZE_STATUS_BITS))) &
+ (DMA_MASK_STATUS_BITS));
+ }
+
+ IOH_DEBUG("Function get_dma_status invoked successfully.\n");
+}
+
+/*! @ingroup HALLayerAPI
+ @fn int dma_set_desc(int channel,
+ struct ioh_dma_desc *start,
+ struct ioh_dma_desc *end)
+ @brief Sets descriptors .
+ @remarks This functions sets the descriptor settings for
+ SCATTER GATHER mode. It does not perform any
+ register settings, instead retains the data for
+ further use. The main tasks performed by this
+ function are:
+ - Sets the pHeadOfList field of the @ref
+ ioh_dma_channel_info structure to the value of
+ the argument start.
+ - Set the pTailOfList field of the @ref
+ ioh_dma_channel_info structure to the value of
+ the argument end.
+
+ @param channel [@ref IN] Channel number.
+ @param start [@ref IN] Reference to first descriptor
+ of list.
+ @param end [@ref IN] Reference to last descriptor
+ of list.
+
+ @see
+ - ioh_set_dma_desc
+ */
+
+int dma_set_desc(int channel, struct ioh_dma_desc *start,
+ struct ioh_dma_desc *end)
+{
+ ioh_dma_channel_info[channel].pHeadOfList = start;
+ ioh_dma_channel_info[channel].pTailOfList = end;
+
+ IOH_DEBUG("Function dma_set_desc returns %d.\n", IOH_DMA_SUCCESS);
+ return IOH_DMA_SUCCESS;
+}
+
+/*! @ingroup InternalFunction
+ @fn void get_free_ch(int index)
+ @brief Get a free channel info entry and populate the entry.
+ @remarks Reset all the entries within the array
+ ioh_dma_channel_info[index]
+
+ @param index [@ref IN] Index in the
+ ioh_dma_channel_table
+
+ @return None
+
+ @see
+ - dma_request_ch
+ */
+void get_free_ch(int index)
+{
+ memset((void *)&ioh_dma_channel_info[index], 0,
+ sizeof(struct ioh_dma_controller_info));
+ IOH_DEBUG("Function get_free_ch invoked successfully.\n");
+}
+
+/*! @ingroup HALLayerAPI
+ @fn int dma_request_ch(u32 req_dev_id, int dreq)
+ @brief Reserves a channel based on request.
+ @remarks This function is invoked when a kernel module requests
+ to reserve a DMA channel. The main tasks
+ performed by this function are:
+ - Checks the @ref ioh_dma_channel_table for a
+ matching entry corresponding to the dev_id of
+ the requesting device and dreq signal.
+ - If there is a matching entry, checks if this
+ channel is already allocated.
+ - If no invoke get_free_ch to reset the entries
+ for the corresponding channel and return the
+ entry index.
+ - If no matching entry is found return -EBUSY.
+
+ @param req_dev_id [@ref IN] Device id of the device
+ that requests DMA .
+ @param dreq [@ref IN] DMA request signal number.
+
+ @return int
+ - DMA channel number (>=0) --> On Success.
+ - -EBUSY --> DMA channel cannot be allocated..
+
+ @see
+ - ioh_request_dma
+ */
+
+int dma_request_ch(u32 req_dev_id, int dreq)
+{
+ int retval;
+ int i;
+
+ for (i = 0; i < IOH_DMA_CHANNELS_MAX; i++) {
+ if ((ioh_dma_channel_table[i].req_device_id == req_dev_id) &&
+ (ioh_dma_channel_table[i].request_signal == dreq)) {
+ if ((1 == ioh_dma_channel_table[i].ch_found) &&
+ (0 == ioh_dma_channel_table[i].ch_alloced)) {
+ get_free_ch(i);
+ IOH_DEBUG
+ ("dma_request_ch -> Function get_free_ch "
+ "invoked successfully.\n");
+ ioh_dma_channel_table[i].ch_alloced = 1;
+ retval = i;
+
+ break;
+ }
+ }
+ }
+
+ if (IOH_DMA_CHANNELS_MAX == i) {
+ retval = -EBUSY;
+ IOH_LOG(KERN_ERR, "dma_request_ch -> Not able to allocate "
+ "channel.\n");
+ }
+
+ IOH_DEBUG("Function dma_request_ch returns %d.\n", retval);
+ return retval;
+}
+
+/*! @ingroup HALLayerAPI
+ @fn int dma_free_ch(int channel)
+ @brief Frees the requested channel.
+ @remarks This function is invoked when a kernel
+ module requests to free a DMA channel. The main
+ tasks performed by this function are:
+ - If the channel is already free return
+ IOH_DMA_SUCCESS.
+ - Else disable the channel by invoking
+ @ref dma_disable_ch API.
+ - Disable the channel interrupt by invoking
+ @ref dma_enable_disable_interrupt
+ - Mark the channel as free in the structures
+ @ref ioh_dma_channel_info and @ref
+ ioh_dma_channel_table and return @ref
+ IOH_DMA_SUCCESS.
+
+ @param channel [@ref IN] DMA channel number to be freed.
+
+ @return int
+ - @ref IOH_DMA_SUCCESS --> On success.
+
+ @see
+ - ioh_free_dma
+ */
+
+int dma_free_ch(int channel)
+{
+ int retval;
+
+ if (ioh_dma_channel_table[channel].ch_alloced == (u16) 0) {
+ IOH_DEBUG("dma_free_ch -> Channel is already free\n");
+ retval = IOH_DMA_SUCCESS;
+ } else {
+ /* To stop any active transfer on DMA, disable DMA */
+ (void)dma_disable_ch(channel);
+ IOH_DEBUG("dma_free_ch -> Function dma_disable_ch invoked "
+ "successfully.\n");
+
+ (void)dma_enable_disable_interrupt(channel,
+ IOH_DMA_INTERRUPT_DISABLE);
+ IOH_DEBUG
+ ("dma_free_ch -> Function dma_enable_disable_interrupt "
+ "invoked successfully.\n");
+
+ ioh_dma_channel_table[channel].ch_alloced = 0;
+
+ retval = IOH_DMA_SUCCESS;
+ }
+
+ IOH_DEBUG("Function dma_free_ch returns %d.\n", IOH_DMA_SUCCESS);
+ return retval;
+}
--- /dev/null
+++ b/drivers/dma/pch_dma/pch_dma_hal.h
@@ -0,0 +1,594 @@
+/**
+ * @file ioh_dma_hal.h
+ *
+ * @brief
+ * This file declares the structures & data types used by the HAL
+ * functions of IOH_DMA_CONTROLLER driver.
+ *
+ * @version 0.90
+ * @section
+ * 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; version 2 of the License.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * <hr>
+ */
+
+/*
+ * History:
+ * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD.
+ * All rights reserved.
+ *
+ * created:
+ * WIPRO 03/07/2009
+ * modified:
+ * WIPRO 08/14/2009
+ *
+ */
+
+#ifndef __IOH_DMA_HAL_H__
+#define __IOH_DMA_HAL_H__
+
+#include <linux/interrupt.h>
+#include "pch_dma_main.h"
+
+/*!
+ @defgroup DMA
+*/
+
+/*! @defgroup Global
+ @ingroup DMA
+ @brief This group contains all the global data
+ structures used by the DMA module.
+*/
+
+/*! defgroup InternalFunction
+ @ingroup DMA
+ @brief This group contains all the function which
+ are used by other APIs for performing some
+ small tasks for facilitating the logic
+ of the driver.
+*/
+
+/*! @defgroup PCILayer
+ @ingroup DMA
+ @brief This group contains all the utilities
+ used to interface the DMA module with
+ the PCI subsystem of the Kernel.
+*/
+
+/*! @defgroup InterfaceLayer
+ @ingroup DMA
+ @brief This group contains all the utilities
+ used by the DMA module to interface with
+ the other modules.
+*/
+
+/*! @defgroup HALLayer
+ @ingroup DMA
+ @brief This group contains all the utilities
+ used to DMA module to interact with the
+ hardware.
+*/
+
+/*! @defgroup PCILayerAPI
+ @ingroup PCILayer
+ @brief This group contains the APIs used to
+ interface the DMA module with the PCI
+ subsystem of the Kernel.
+*/
+
+/*! @defgroup PCILayerFacilitators
+ @ingroup PCILayer
+ @brief This group contains the data structures
+ used by the PCILayerAPIs for their
+ functioning.
+*/
+
+/*! @defgroup HALLayerAPI
+ @ingroup HALLayer
+ @brief This group contains the APIs used to
+ communicate with the hardware.
+*/
+
+/*! @defgroup HALLayerFacilitators
+ @ingroup HALLayer
+ @brief This group contains the data structures
+ used to communicate with the hardware.
+*/
+
+/*! @defgroup InterfaceLayerAPI
+ @ingroup InterfaceLayer
+ @brief This group contains the APIs used by the
+ DMA module to interface with other modules.
+*/
+
+/*! @defgroup InterfaceLayerFacilitators
+ @ingroup InterfaceLayer
+ @brief This group contains the data structures
+ used by the DMA module to interface with
+ other modules.
+*/
+
+/*** Device specific limitations and properties. ***/
+
+/*! @ingroup DMA
+ @def IOH_DMA_CHANNELS_MAX
+ @brief The maximum number of channels allowed
+ in any of the IOH device.
+*/
+#define IOH_DMA_CHANNELS_MAX (64)
+
+/*! @ingroup DMA
+ @def IOH_DMA_MAX_DEVS
+ @brief The no. of DMA devices allowable.
+
+ @see
+ - ioh_dma_devices
+*/
+#define IOH_DMA_MAX_DEVS (4)
+
+/*! @ingroup DMA
+ @def IOH_DMA_8BIT_SIZE_MAX
+ @brief The maximum number of transfer size in
+ bytes for a channel if access size is set
+ to 8BIT.
+*/
+#define IOH_DMA_8BIT_SIZE_MAX (2047)
+
+/*! @ingroup DMA
+ @def IOH_DMA_16BIT_SIZE_MAX
+ @brief The maximum number of transfer size in
+ bytes for a channel if access size is set
+ to 16BIT.
+*/
+#define IOH_DMA_16BIT_SIZE_MAX (4094)
+
+/*! @ingroup DMA
+ @def IOH_DMA_32BIT_SIZE_MAX
+ @brief The maximum number of transfer size in
+ bytes for a channel if access size is set
+ to 32BIT.
+*/
+#define IOH_DMA_32BIT_SIZE_MAX (4096)
+
+/********/
+
+/*** Device IDs of DMA requesting devices. ***/
+/*! @ingroup DMA
+ @def PCI_DEVICE_ID_IOH_UART0
+ @brief The deviceID of the IOH GE UART
+ device 0 which can use the DMA features.
+*/
+#define PCI_DEVICE_ID_IOH_UART0 (0x8811)
+
+/*! @ingroup DMA
+ @def PCI_DEVICE_ID_IOH_UART1
+ @brief The deviceID of the IOH GE UART
+ device 1 which can use the DMA features.
+*/
+#define PCI_DEVICE_ID_IOH_UART1 (0x8812)
+
+/*! @ingroup DMA
+ @def PCI_DEVICE_ID_IOH_UART2
+ @brief The deviceID of the IOH GE UART
+ device 2 which can use the DMA features.
+*/
+#define PCI_DEVICE_ID_IOH_UART2 (0x8813)
+
+/*! @ingroup DMA
+ @def PCI_DEVICE_ID_IOH_UART3
+ @brief The deviceID of the IOH GE UART
+ device 3 which can use the DMA features.
+*/
+#define PCI_DEVICE_ID_IOH_UART3 (0x8814)
+
+/*! @ingroup DMA
+ @def PCI_DEVICE_ID_IOH_SPI
+ @brief The deviceID of the IOH GE SPI
+ device which can use the DMA features.
+*/
+#define PCI_DEVICE_ID_IOH_SPI (0x8816)
+
+/*** Internal device IDs used for identifing the DMAC . ***/
+/*! @ingroup Global
+ @def IOH_DMA_4CH0
+ @brief The device ID for the first DMA device
+ with 4 channels.
+*/
+#define IOH_DMA_4CH0 (0x40)
+
+/*! @ingroup Global
+ @def IOH_DMA_4CH1
+ @brief The device ID for the second DMA device
+ with 4 channels.
+*/
+#define IOH_DMA_4CH1 (0x41)
+
+/*! @ingroup Global
+ @def IOH_DMA_4CH2
+ @brief The device ID for the third DMA device
+ with 4 channels.
+*/
+#define IOH_DMA_4CH2 (0x42)
+
+/*! @ingroup Global
+ @def IOH_DMA_4CH3
+ @brief The device ID for the fourth DMA device
+ with 4 channels.
+*/
+#define IOH_DMA_4CH3 (0x43)
+
+/*! @ingroup Global
+ @def IOH_DMA_4CH4
+ @brief The device ID for the fifth DMA device
+ with 4 channels.
+*/
+#define IOH_DMA_4CH4 (0x44)
+
+/*! @ingroup Global
+ @def IOH_DMA_8CH0
+ @brief The device ID for the first DMA device
+ with 8 channels.
+*/
+#define IOH_DMA_8CH0 (0x80)
+
+/*! @ingroup Global
+ @def IOH_DMA_8CH1
+ @brief The device ID for the second DMA device
+ with 8 channels.
+*/
+#define IOH_DMA_8CH1 (0x81)
+
+/*! @ingroup Global
+ @def IOH_DMA_8CH2
+ @brief The device ID for the third DMA device
+ with 8 channels.
+*/
+#define IOH_DMA_8CH2 (0x82)
+
+/*! @ingroup Global
+ @def IOH_DMA_8CH3
+ @brief The device ID for the fourth DMA device
+ with 8 channels.
+*/
+#define IOH_DMA_8CH3 (0x83)
+
+/*! @ingroup Global
+ @def IOH_DMA_12CH0
+ @brief The device ID for the first DMA device
+ with 12 channels.
+*/
+#define IOH_DMA_12CH0 (0xC0)
+
+/******/
+
+/*** DMA Controller Register Offsets. ***/
+
+/*! @ingroup HALLayer
+ @def DMA_CTL0_OFFSET
+ @brief DMA Control register 0 offset.
+*/
+#define DMA_CTL0_OFFSET (0x00UL)
+
+/*! @ingroup HALLayer
+ @def DMA_CTL1_OFFSET
+ @brief DMA Control register 1 offset.
+*/
+#define DMA_CTL1_OFFSET (0x04UL)
+
+/*! @ingroup HALLayer
+ @def DMA_CTL2_OFFSET
+ @brief DMA Control register 2 offset.
+*/
+#define DMA_CTL2_OFFSET (0x08UL)
+
+/*! @ingroup HALLayer
+ @def DMA_CTL3_OFFSET
+ @brief DMA Control register 3 offset.
+*/
+#define DMA_CTL3_OFFSET (0x0CUL)
+
+/*! @ingroup HALLayer
+ @def DMA_STS0_OFFSET
+ @brief DMA Status register 0 offset.
+*/
+#define DMA_STS0_OFFSET (0x10UL)
+
+/*! @ingroup HALLayer
+ @def DMA_STS1_OFFSET
+ @brief DMA Status register 1 offset.
+*/
+#define DMA_STS1_OFFSET (0x14UL)
+
+/*! @ingroup HALLayer
+ @def DMA_STS2_OFFSET
+ @brief DMA Status register 2 offset.
+*/
+#define DMA_STS2_OFFSET (0x18UL)
+
+/*! @ingroup HALLayer
+ @def DMA_IN_AD_OFFSET
+ @brief DMA IN Address register offset.
+*/
+#define DMA_IN_AD_OFFSET (0x20UL)
+
+/*! @ingroup HALLayer
+ @def DMA_OUT_AD_OFFSET
+ @brief DMA Out Address register offset.
+*/
+#define DMA_OUT_AD_OFFSET (0x24UL)
+
+/*! @ingroup HALLayer
+ @def DMA_SZ_OFFSET
+ @brief DMA Size register offset.
+*/
+#define DMA_SZ_OFFSET (0x28UL)
+
+/*! @ingroup HALLayer
+ @def DMA_NX_AD_OFFSET
+ @brief DMA Next Address register offset.
+*/
+#define DMA_NX_AD_OFFSET (0x2CUL)
+
+/**********/
+
+/*** Individual register bits. ***/
+
+/*! @ingroup HALLayer
+ @def DMA_SIZE_TYPE_BITS
+ @brief The DMA size bits.
+*/
+#define DMA_SIZE_TYPE_BITS (0x00003000UL)
+
+/*! @ingroup HALLayer
+ @def DMA_SET_OR_CLEAR_DIR_BIT
+ @brief Mask for direction bit.
+*/
+#define DMA_SET_OR_CLEAR_DIR_BIT (0x00000004UL)
+
+/*! @ingroup HALLayer
+ @def DMA_MASK_MODE_BITS
+ @brief Mask for mode bits.
+*/
+#define DMA_MASK_MODE_BITS (0x00000003UL)
+
+/*! @ingroup HALLayer
+ @def DMA_SHIFT_MODE_BITS
+ @brief DMA shift mode bits.
+*/
+#define DMA_SHIFT_MODE_BITS (4)
+
+/*! @ingroup HALLayer
+ @def DMA_MASK_PRIORITY_BITS
+ @brief Mask for priority bits.
+*/
+#define DMA_MASK_PRIORITY_BITS (0x3UL)
+
+/*! @ingroup HALLayer
+ @def DMA_SHIFT_PRIORITY_BITS
+ @brief Shift value for DMA priority bits.
+*/
+#define DMA_SHIFT_PRIORITY_BITS (4)
+
+/*! @ingroup HALLayer
+ @def DMA_SHIFT_SIZE_TYPE_BITS
+ @brief Shift value for the DMA size bit.
+*/
+#define DMA_SHIFT_SIZE_TYPE_BITS (12)
+
+/*! @ingroup HALLayer
+ @def DMA_DIR_START
+ @brief Direct Start Bit Setting values.
+*/
+#define DMA_DIR_START (0x00000100UL)
+
+/*! @ingroup HALLayer
+ @def DMA_INTERRUPT_BIT
+ @brief Interrupt Enable Bit setting values.
+*/
+#define DMA_INTERRUPT_BIT (0x00000001UL)
+
+/*! @ingroup HALLayer
+ @def DMA_ABORT_OCCUR
+ @brief Abort notify Bit Setting Values
+*/
+#define DMA_ABORT_OCCUR (0x00000100UL)
+
+/*! @ingroup HALLayer
+ @def DMA_INTERRUPT_OCCUR
+ @brief Interrupt notify Bit Setting Values
+*/
+#define DMA_INTERRUPT_OCCUR (0x00000001UL)
+
+/*! @ingroup HALLayer
+ @def DMA_MASK_STATUS_BITS
+ @brief Mask for status bits.
+*/
+#define DMA_MASK_STATUS_BITS (0x3UL)
+
+/*! @ingroup HALLayer
+ @def DMA_SIZE_STATUS_BITS
+ @brief The DMA size status bits.
+*/
+#define DMA_SIZE_STATUS_BITS (2)
+
+/*! @ingroup HALLayer
+ @def DMA_SHIFT_STATUS_BITS
+ @brief The shift value for DMA status bits.
+*/
+#define DMA_SHIFT_STATUS_BITS (16)
+
+/*********/
+
+/*** Status denoting macros. ***/
+
+/*! @ingroup HALLayer
+ @def DMA_STATUS_IDLE
+ @brief Constant used to denote the transfer status as IDLE.
+ @note This constant is used by DMA modules to make the
+ other module aware of the DMA status.
+*/
+#define DMA_STATUS_IDLE (0)
+
+/*! @ingroup HALLayer
+ @def DMA_STATUS_DESC_READ
+ @brief Constant used to denote the transfer status as
+ DESCRIPTOR_READ.
+ @note This constant is used by DMA modules to make the
+ other module aware of the DMA status.
+*/
+#define DMA_STATUS_DESC_READ (1)
+
+/*! @ingroup HALLayer
+ @def DMA_STATUS_WAIT
+ @brief Constant used to denote the transfer status as WAIT.
+ @note This constant is used by DMA modules to make the
+ other module aware of the DMA status.
+*/
+#define DMA_STATUS_WAIT (2)
+
+/*! @ingroup HALLayer
+ @def DMA_STATUS_ACCESS
+ @brief Constant used to denote the transfer status as ACCESS
+ @note This constant is used by DMA modules to make the
+ other module aware of the DMA status.
+*/
+#define DMA_STATUS_ACCESS (3)
+
+/*! @ingroup HALLayer
+ @def IOH_DMA_INTERRUPT_DISABLE
+ @brief Constant used to denote disable interrupt.
+*/
+#define IOH_DMA_INTERRUPT_DISABLE (0)
+
+/*! @ingroup HALLayer
+ @def IOH_DMA_INTERRUPT_ENABLE
+ @brief Constant used to denote enable interrupt.
+*/
+#define IOH_DMA_INTERRUPT_ENABLE (1)
+
+/************/
+
+/*** Other Macros. ***/
+
+/*! @ingroup HALLayer
+ @def COUNTER_LIMIT
+ @brief The counter limit.
+*/
+#define COUNTER_LIMIT (0xFFFF)
+
+/*! @ingroup HALLayer
+ @def MSK_ALL_THREE
+ @brief Value used for masking the 3 LSB bits.
+*/
+#define MSK_ALL_THREE (0x7)
+
+/*******/
+/*** Data Structures for stroing device specific information. ***/
+
+/*! @ingroup HALLayerFacilitators
+ @struct __ioh_dma_devices
+ @brief Format for maintaining the device information.
+ @note This structure is used by the DMA module to retain
+ the information about the device.
+
+ @see
+ - ioh_dma_devices
+*/
+
+struct ioh_dma_devices {
+ u32 base_addr; /**< The remapped base address. */
+ u32 dev_typ; /**< The device type indicating number of DMA
+ channels */
+ void *dev; /**< The void pointer for storing any references
+ if required */
+};
+
+/*! @ingroup HALLayerFacilitators
+ @struct __ioh_dma_controller_info_t
+ @brief Format for storing the details of the
+ DMA channels.
+*/
+
+struct ioh_dma_controller_info {
+ u16 DMATransferMode; /**< DMA Transfer Mode */
+ u16 bChEnabled; /**< To know if channel is enabled or
+ not */
+ struct ioh_dma_desc *pHeadOfList; /**< Pointer to start
+ descriptor */
+ struct ioh_dma_desc *pTailOfList; /**< Pointer to last
+ descriptor */
+ void (*call_back_func_ptr) (int, unsigned long);/**< Address of the call
+ back function that is to be called when
+ an interrupt occurs */
+ u32 callback_data; /**< The data to passed to the callback
+ function during invocation */
+ u16 DMAAccessSize; /**< To store the access size (8bit,
+ 16bit or 32bit) */
+ u16 DMATransferSize; /**< To store the value of Transfer
+ Size */
+ u16 DMATransferDirection; /**< To store the Direction of Transfer
+ (IN to OUT or OUT to IN) */
+ u32 in_addr; /**< The in_address */
+ u32 out_addr; /**< The out_address */
+};
+
+/*! @ingroup HALLayerFacilitators
+ @struct ioh_dma_channel_alloc_table
+ @brief Format for storing the details of the
+ allocation details of the DMA channels.
+*/
+
+struct ioh_dma_channel_alloc_table {
+ u32 dma_dev_id; /**< The DMA device ID. */
+ enum ioh_channel_request_id request_signal; /**< The request type.*/
+ u32 req_device_id; /**< The device ID of the requested device */
+ u16 channel; /**< The channel number. */
+ u16 ch_found:1; /**< The flag variable for channel in use */
+ u16 ch_alloced:1; /**< The flag variable for channel allocate. */
+ u32 base; /**< The base address of the DMA device. */
+};
+
+ /*****/
+
+extern struct ioh_dma_channel_alloc_table
+ ioh_dma_channel_table[IOH_DMA_CHANNELS_MAX];
+extern struct ioh_dma_controller_info
+ ioh_dma_channel_info[IOH_DMA_CHANNELS_MAX];
+
+void dma_init(u32 base, u32 dev_type);
+int dma_free_ch(int channel);
+int dma_request_ch(u32 req_dev_id, int dreq);
+int dma_set_mode(int channel, struct ioh_dma_mode_param stModeParam);
+int dma_set_addr(int channel, u32 iaddr, u32 oaddr);
+int dma_enable_ch(int channel);
+int dma_disable_ch(int channel);
+int dma_set_count(int channel, u32 count);
+int dma_add_desc(int channel, struct ioh_dma_desc *start,
+ struct ioh_dma_desc *end);
+int dma_set_desc(int channel, struct ioh_dma_desc *start,
+ struct ioh_dma_desc *end);
+void dma_set_callback(int channel,
+ void (*ioh_dma_cbr) (int value, unsigned long data1),
+ unsigned long data);
+irqreturn_t dma_interrupt(int irq, void *dev_id);
+int dma_set_priority(int channel, int priority);
+int dma_direct_start(int channel);
+int dma_enable_disable_interrupt(int channel, int bEnable);
+void dma_get_abort_status(int channel, u16 *pAbortStatus);
+void dma_get_interrupt_status(int channel, u16 *pInterruptStatus);
+void get_dma_status(int channel, u16 *pDMAStatus);
+void get_free_ch(int index);
+void dma_exit(u32 dev_type);
+
+#endif
--- /dev/null
+++ b/drivers/dma/pch_dma/pch_dma_main.c
@@ -0,0 +1,1026 @@
+/**
+ * @file ioh_dma_main.c
+ *
+ * @brief
+ * This file defines the methods of IOH_DMA driver.
+ *
+ *
+ * @version 0.90
+ * @section
+ * 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; version 2 of the License.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * <hr>
+ */
+
+/*
+ * History:
+ * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD.
+ * All rights reserved.
+ *
+ * created:
+ * WIPRO 03/07/2009
+ * modified:
+ * WIPRO 08/14/2009
+ *
+ */
+
+#include <linux/spinlock.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+
+#include "pch_debug.h"
+#include "pch_dma_hal.h"
+#include "pch_dma_pci.h"
+
+
+/*! @ingroup InterfaceLayerAPI
+ @fn int ioh_request_dma(struct pci_dev *pdev, int dreq)
+ @brief Used to request a DMA channel.
+ @remarks Requests to reserve a DMA channel that connects
+ to number 'dreq' (DMA request signal) of PCI
+ device 'pdev' to the appropriate DMA channel
+ allocated for it within the DMA Controller. This
+ function is called by functions from other
+ kernel modules. The tasks performed by this
+ function are:
+ - Verifies whether the obtained parameters are
+ valid,
+ if not suitable error status codes are returned
+ to the called function.
+ - If valid interacts with the HAL API and
+ returns the status code returned by the HAL API.
+
+ @note This function is accessible by other kernel modules.
+
+ @param dev [@ref IN] PCI device that requires the DMA
+ channel.
+ @param dreq [@ref IN] DMA request signal number.
+
+ @return int
+ - @ref IOH_DMA_SUCCESS --> On success.
+ - -EAGAIN --> Device is in suspend mode.
+ - -EINVAL --> pdev does not have a DMA request
+ type or number 'dreq' or 'pdev'
+ is NULL.
+*/
+int ioh_request_dma(struct pci_dev *pdev, int dreq)
+{
+ int retval;
+
+ /* Attaining the lock. */
+ spin_lock(&ioh_device_lock);
+
+ /* If device suspended. */
+ if (1 == ioh_device_suspended) {
+ IOH_LOG(KERN_ERR,
+ "ioh_request_dma -> Device is in suspend mode.\n");
+ retval = -EAGAIN;
+ }
+ /* Invalid device structure. */
+ else if (NULL == pdev) {
+ IOH_LOG(KERN_ERR,
+ "ioh_request_dma -> Obtained device structure "
+ "is NULL.\n");
+ retval = -EINVAL;
+ }
+ /* Invalid request signal. */
+ else if ((dreq < IOH_DMA_TX_DATA_REQ0) ||
+ (dreq > IOH_DMA_RX_DATA_REQ5)) {
+ IOH_LOG(KERN_ERR,
+ "ioh_request_dma -> Invalid request signal.\n");
+ retval = -EINVAL;
+ } else {
+ /* Requesting for reserving a DMA channel. */
+ retval = dma_request_ch((u32) (pdev->device), dreq);
+ IOH_DEBUG("ioh_request_dma -> Function dma_request_ch returned "
+ "%d.\n", retval);
+ }
+
+ /* Releasing the lock. */
+ spin_unlock(&ioh_device_lock);
+
+ IOH_DEBUG("Function ioh_request_dma returns %d.\n", retval);
+ return retval;
+}
+EXPORT_SYMBOL(ioh_request_dma);
+
+/*! @ingroup InterfaceLayerAPI
+ @fn int ioh_free_dma(int channel)
+ @brief Used to free a DMA channel.
+ @remarks Frees the allocated DMA channel that is provided
+ as the argument to the function. This function
+ is called by the functions from other kernel
+ modules. The main tasks performed by this
+ function are:
+ - Verifies whether the obtained parameters are
+ valid, if not suitable error status codes are
+ returned to the called function.
+ - If valid interacts with the HAL API for
+ freeing the channel and returns the status code
+ returned by the HAL API.
+ @note This function is accessible by other kernel
+ modules.
+
+ @param channel [@ref IN] DMA channel number
+
+ @return int
+ - @ref IOH_DMA_SUCCESS --> On success.
+ - -EAGAIN --> Device is in suspend mode.
+ - -ENODEV --> Specified DMA channel does
+ not exist.
+*/
+int ioh_free_dma(int channel)
+{
+ int retval;
+
+ if (1 == ioh_device_suspended) {
+ IOH_LOG(KERN_ERR,
+ "ioh_free_dma -> Device is in suspend mode.\n");
+ retval = -EAGAIN;
+ } else if ((channel >= IOH_DMA_CHANNELS_MAX) || (channel < 0)) {
+ IOH_LOG(KERN_ERR, "ioh_free_dma -> Invalid Channel number: "
+ "%d.\n", channel);
+ retval = -ENODEV;
+ } else {
+ retval = dma_free_ch(channel);
+ IOH_DEBUG("ioh_free_dma -> Function dma_free_ch "
+ "returned %d.\n", retval);
+ }
+
+ IOH_DEBUG("Function ioh_free_dma returns %d.\n", retval);
+ return retval;
+}
+EXPORT_SYMBOL(ioh_free_dma);
+
+/*! @ingroup InterfaceLayerAPI
+ @fn int ioh_set_dma_mode(int channel,struct
+ ioh_dma_mode_param stModeParam)
+ @brief Used to set the mode of the DMA.
+ @remarks Sets the mode of DMA transfer - One shot mode
+ or Scatter/gather mode. In addition to this,
+ the function also sets the direction of DMA
+ transfer and DMA Size type. This function is
+ called by functions from other kernel modules.
+ The main tasks performed by this function are:
+ - Verifies whether the obtained parameters are
+ valid, if not suitable error status codes are
+ returned to the called function.
+ - If valid interacts with the HAL API to set the
+ required settings and returns the status code
+ returned by the HAL API.
+
+ @note This function is accessible by other kernel modules.
+
+ @param channel [@ref IN] DMA channel number
+ @param stModeParam [@ref IN] Contains info about
+ direction of DMA transfer, mode
+ and Size type
+
+ @return int
+ - @ref IOH_DMA_SUCCESS --> On success.
+ - -EAGAIN --> The device is in suspend
+ mode.
+ - -ENODEV --> Specified DMA channel does
+ not exist.
+ - -EINVAL --> Parameter passed is invalid.
+ - -EBUSY --> DMA channel is already
+ enabled.
+*/
+int ioh_set_dma_mode(int channel, struct ioh_dma_mode_param stModeParam)
+{
+ int retval;
+
+ /* Checking if device suspended. */
+ if (1 == ioh_device_suspended) {
+ IOH_LOG(KERN_ERR,
+ "ioh_set_dma_mode -> Device is in suspend mode.\n");
+ retval = -EAGAIN;
+ }
+ /* Checking for validity of channel number. */
+ else if ((channel >= IOH_DMA_CHANNELS_MAX) || (channel < 0)) {
+ IOH_LOG(KERN_ERR,
+ "ioh_set_dma_mode -> Invalid Channel number : " "%d.\n",
+ channel);
+ retval = -ENODEV;
+ }
+ /* Checking whether channel not allocated. */
+ else if (ioh_dma_channel_table[channel].ch_alloced == (u16) 0) {
+ IOH_LOG(KERN_ERR,
+ "ioh_set_dma_mode -> Channel not allocated.\n");
+ retval = -EINVAL;
+ }
+ /* Checking if channel already enabled. */
+ else if (ioh_dma_channel_info[channel].bChEnabled == 1) {
+ IOH_LOG(KERN_ERR,
+ "ioh_set_dma_mode -> Channel already enabled.\n");
+ retval = -EBUSY;
+ }
+ /* Checking for validity of DMA Transfer MODE. */
+ else if ((stModeParam.DMATransferMode != (u16) DMA_ONE_SHOT_MODE) &&
+ (stModeParam.DMATransferMode !=
+ (u16) DMA_SCATTER_GATHER_MODE)) {
+ IOH_LOG(KERN_ERR,
+ "ioh_set_dma_mode -> Invalid DMA Transfer mode.\n");
+ retval = -EINVAL;
+ }
+ /* Checking for validity of Transfer Direction. */
+ else if ((stModeParam.TransferDirection != (u16) IOH_DMA_DIR_OUT_TO_IN)
+ && (stModeParam.TransferDirection !=
+ (u16) IOH_DMA_DIR_IN_TO_OUT)) {
+ IOH_LOG(KERN_ERR,
+ "ioh_set_dma_mode -> Invalid DMA Transfer Direction." \
+ "\n");
+ retval = -EINVAL;
+ }
+ /* Checking for validity of Transfer Size Type. */
+ else if ((stModeParam.DMASizeType != (u16) IOH_DMA_SIZE_TYPE_8BIT) &&
+ (stModeParam.DMASizeType != (u16) IOH_DMA_SIZE_TYPE_16BIT) &&
+ (stModeParam.DMASizeType != (u16) IOH_DMA_SIZE_TYPE_32BIT)) {
+ IOH_LOG(KERN_ERR,
+ "ioh_set_dma_mode -> Invalid DMA Size Type.\n");
+ retval = -EINVAL;
+ } else {
+ /* Setting the required DMA mode. */
+ retval = dma_set_mode(channel, stModeParam);
+ IOH_DEBUG("ioh_set_dma_mode -> Function dma_set_mode "
+ "returned %d.\n", retval);
+ }
+
+ IOH_DEBUG("Function ioh_set_dma_mode returns %d.\n", retval);
+ return retval;
+}
+EXPORT_SYMBOL(ioh_set_dma_mode);
+
+/*! @ingroup InterfaceLayerAPI
+ @fn int ioh_set_dma_addr(int channel, unsigned int iaddr,
+ unsigned int oaddr)
+ @brief Used to set the in and out address of the DMA channel.
+ @remarks Sets the address of the inside bridge and the outside
+ bridge for the 'One Shot Mode' of DMA Transfer.
+ This function is invoked by functions from other
+ modules. The main tasks performed by this
+ function are:
+ - Verifies whether the obtained parameters are
+ valid, if not suitable error status codes are
+ returned to the called function.
+ - If valid interacts with the HAL API to set the
+ inside and outside address and returns the
+ status code returned by the HAL API.
+ @note This function is accessible by other kernel modules. The
+ following points has to be noted while passing
+ the in-address and out-address paramter.
+ - The address passed should be valid physical
+ address within the memory space.
+ - It should not be a configuration space or IO
+ space address.
+ - If the transfer is for large data, the address
+ should point to contagious alligned memory space
+ .
+
+ @param channel [@ref IN] DMA channel number .
+ @param iaddr [@ref IN] Address of inside bridge.
+ @param oaddr [@ref IN] Address of outside bridge.
+
+ @return int
+ - @ref IOH_DMA_SUCCESS --> On success.
+ - -EAGAIN --> The device is in suspend mode.
+ - -ENODEV --> Specified DMA channel does not exist.
+ - -EINVAL --> Parameter passed is invalid.
+ - -EBUSY --> DMA transfer in progress or channel is
+ already enabled.
+
+*/
+int ioh_set_dma_addr(int channel, unsigned int iaddr, unsigned int oaddr)
+{
+ int retval;
+
+ /* If the device is in suspend mode. */
+ if (1 == ioh_device_suspended) {
+ IOH_LOG(KERN_ERR,
+ "ioh_set_dma_addr -> Device is in suspend mode.\n");
+ retval = -EAGAIN;
+ }
+ /* Checking for validity of channel number */
+ else if ((channel >= IOH_DMA_CHANNELS_MAX) || (channel < 0)) {
+ IOH_LOG(KERN_ERR, "ioh_set_dma_addr -> Invalid Channel "
+ "number: %d.\n", channel);
+ retval = -ENODEV;
+ }
+ /* Checking whether channel is not allocated. */
+ else if (ioh_dma_channel_table[channel].ch_alloced == (u16) 0) {
+ IOH_LOG(KERN_ERR, "ioh_set_dma_addr -> Channel not "
+ "allocated.\n");
+ retval = -EINVAL;
+ }
+ /* Checking whether the channel is already enabled. */
+ else if (ioh_dma_channel_info[channel].bChEnabled == 1) {
+ IOH_LOG(KERN_ERR, "ioh_set_dma_addr -> Channel already "
+ "enabled.\n");
+ retval = -EBUSY;
+ }
+ /*Checking if addresses specified are NULL or not */
+ else if ((iaddr == 0) || (oaddr == 0)) {
+ IOH_LOG(KERN_ERR, "ioh_set_dma_addr -> Invalid address.\n");
+ retval = -EINVAL;
+ }
+ /* Checking if the mode of transfer is other than ONE_SHOT. */
+ else if (ioh_dma_channel_info[channel].DMATransferMode !=
+ (u16) DMA_ONE_SHOT_MODE) {
+ IOH_LOG(KERN_ERR,
+ "ioh_set_dma_addr -> Current Mode is "
+ "not DMA_ONE_SHOT_MODE.\n");
+ retval = -EINVAL;
+ } else {
+ /* setting the in and out address. */
+ retval = dma_set_addr(channel, iaddr, oaddr);
+ IOH_DEBUG("ioh_set_dma_addr -> Function dma_set_addr invoked "
+ "successfully returned %d.\n", retval);
+ }
+
+ IOH_DEBUG("Function ioh_set_dma_addr returns %d.\n", retval);
+ return retval;
+}
+EXPORT_SYMBOL(ioh_set_dma_addr);
+
+/*! @ingroup InterfaceLayerAPI
+ @fn int ioh_set_dma_count(int channel, unsigned int count)
+ @brief Used to set the DMA transfer count for a DMA channel.
+ @remarks Sets the value of DMA transfer count. This function
+ sets the count value only for the 'One Shot
+ Mode' of DMA Transfer. This function is invoked
+ by functions from other modules. The main tasks
+ performed by this function are:
+ - Verifies whether the obtained parameters are
+ valid, if not suitable error status codes are
+ returned to the called function.
+ - If valid interacts with the HAL API to set the
+ access count settings and returns the status
+ code returned by the HAL API.
+ @note This function is accessible by other kernel modules.
+
+ @param channel [@ref IN] DMA channel number.
+ @param count [@ref IN] The number of bytes to transfer.
+
+ @return int
+ - @ref IOH_DMA_SUCCESS --> On success.
+ - -EAGAIN --> The device is in suspend mode.
+ - -ENODEV --> Specified DMA channel does not
+ exist.
+ - -EBUSY --> DMA transfer in progress or channel
+ is already enabled.
+ - -EINVAL --> Parameter passed is invalid.
+
+ */
+int ioh_set_dma_count(int channel, unsigned int count)
+{
+ int retval = IOH_DMA_SUCCESS;
+
+ /* Checking if the device is in suspend mode. */
+ if (1 == ioh_device_suspended) {
+ IOH_LOG(KERN_ERR, "ioh_set_dma_count -> The device is in "
+ "suspend mode.");
+ retval = -EAGAIN;
+ }
+ /* Checking for validity of channel number. */
+ else if ((channel >= IOH_DMA_CHANNELS_MAX) || (channel < 0)) {
+ IOH_LOG(KERN_ERR, "ioh_set_dma_count -> Invalid Channel "
+ "number : %d.\n", channel);
+ retval = -ENODEV;
+ }
+ /* Checking whether channel is not allocated. */
+ else if (ioh_dma_channel_table[channel].ch_alloced == (u16) 0) {
+ IOH_LOG(KERN_ERR, "ioh_set_dma_count -> Channel is not "
+ "allocated.\n");
+ retval = -EINVAL;
+ }
+ /* Checking whether the channel is enabled. */
+ else if (ioh_dma_channel_info[channel].bChEnabled == 1) {
+ IOH_LOG(KERN_ERR, "ioh_set_dma_count -> Channel already "
+ "enabled.\n");
+ retval = -EBUSY;
+ }
+ /* Checking if the mode of transfer is other than ONE_SHOT. */
+ else if (ioh_dma_channel_info[channel].DMATransferMode !=
+ (u16) DMA_ONE_SHOT_MODE) {
+ IOH_LOG(KERN_ERR,
+ "ioh_set_dma_count -> Current Mode is "
+ "not DMA_ONE_SHOT_MODE.\n");
+ retval = -EINVAL;
+ }
+ /* Checking the limits of count value. */
+ else {
+ unsigned int max_count;
+
+ switch (ioh_dma_channel_info[channel].DMAAccessSize) {
+ case IOH_DMA_SIZE_TYPE_8BIT:
+ max_count = IOH_DMA_8BIT_COUNT_MAX;
+ break;
+
+ case IOH_DMA_SIZE_TYPE_16BIT:
+ max_count = IOH_DMA_16BIT_COUNT_MAX;
+ break;
+
+ case IOH_DMA_SIZE_TYPE_32BIT:
+ max_count = IOH_DMA_32BIT_COUNT_MAX;
+ break;
+
+ default:
+ IOH_LOG(KERN_ERR, "ioh_set_dma_count -> Invalid Access "
+ "Size.\n");
+ max_count = 0;
+ retval = -EINVAL;
+ break;
+ }
+
+ if ((retval == IOH_DMA_SUCCESS) && (count > max_count)) {
+ IOH_LOG(KERN_ERR,
+ "ioh_set_dma_count -> Count (%d) exceeds "
+ "limit the maximum expected count (%d).\n",
+ count, max_count);
+ retval = -EINVAL;
+ }
+ }
+
+ if (IOH_DMA_SUCCESS == retval) {
+ /* Setting the count. */
+ retval = dma_set_count(channel, count);
+ IOH_DEBUG
+ ("ioh_set_dma_count -> Function dma_set_count returned "
+ "%d.\n", retval);
+ }
+
+ IOH_DEBUG("Function ioh_set_dma_count returns %d.\n", retval);
+ return retval;
+}
+EXPORT_SYMBOL(ioh_set_dma_count);
+
+/*! @ingroup InterfaceLayerAPI
+ @fn int ioh_set_dma_desc(int channel, struct ioh_dma_desc *start,
+ struct ioh_dma_desc *end)
+ @brief Used to set the DMA channel descriptors.
+ @remarks Sets the DMA descriptor for the 'Scatter/Gather mode'
+ of DMA transfer. This function is invoked by
+ functions from other kernel modules. The main
+ tasks performed by this function are:
+ - Verifies whether the obtained parameters are
+ valid, if not suitable error status codes are
+ returned to the called function.
+ - If valid interacts with the HAL API to set the
+ descriptor settings and returns the status code
+ returned by the HAL API.
+ @note This function is accessible by other kernel modules. The
+ following points have to be noted while passing
+ the "start" and "end" pointer of the descriptor.
+ - The address pointed by them should be physical
+ address with valid virtual address.
+ - The space should be alligned and accessible by
+ the DMA hardware.
+ - An easy way to perform this is to allocate the
+ descriptor memory using kmalloc.
+ - The last two bits of the physical address
+ should be suitably set so as to perform suitable
+ action after completion of each descriptor
+ action.
+ - The in-address and out-address within each
+ descriptor should be a valid memory space
+ physical address.
+
+ @param channel [@ref IN] DMA channel number
+ @param start [@ref IN] A pointer to the first descriptor.
+ @param end [@ref IN] A pointer to the last descriptor.
+
+ @return int
+ - @ref IOH_DMA_SUCCESS --> On success.
+ - -EAGAIN --> The device is in suspend.
+ - -EINVAL --> For invalid parameters.
+ - -ENODEV --> Specified DMA channel is not exist.
+ - -EBUSY --> If DMA transfer is in progress or
+ channel is already enabled.
+*/
+int ioh_set_dma_desc(int channel, struct ioh_dma_desc *start,
+ struct ioh_dma_desc *end)
+{
+ int retval;
+
+ /* Checking if the device is in suspend mode. */
+ if (1 == ioh_device_suspended) {
+ IOH_LOG(KERN_ERR, "ioh_set_dma_desc -> The device is in "
+ "suspend mode.\n");
+ retval = -EAGAIN;
+ }
+ /* Checking for validity of channel number */
+ else if ((channel >= IOH_DMA_CHANNELS_MAX) || (channel < 0)) {
+ IOH_LOG(KERN_ERR, "ioh_set_dma_desc -> Invalid Channel number "
+ ": %d.\n", channel);
+ retval = -ENODEV;
+ }
+ /* Checking whether channel is not allocated. */
+ else if (ioh_dma_channel_table[channel].ch_alloced == (u16) 0) {
+ IOH_LOG(KERN_ERR,
+ "ioh_set_dma_desc -> Channel not allocated.\n");
+ retval = -EINVAL;
+ }
+ /* Checking whether the channel is enabled. */
+ else if (ioh_dma_channel_info[channel].bChEnabled == 1) {
+ IOH_LOG(KERN_ERR,
+ "ioh_set_dma_desc -> Channel already enabled.\n");
+ retval = -EBUSY;
+ }
+ /* Checking if the mode is other than SCATTER_GATHER. */
+ else if (ioh_dma_channel_info[channel].DMATransferMode !=
+ (u16) DMA_SCATTER_GATHER_MODE) {
+ IOH_LOG(KERN_ERR,
+ "ioh_set_dma_desc -> Current mode id is not "
+ "SCATTER GATHER.\n");
+ retval = -EINVAL;
+ }
+ /* Checking whether start and end pointers are NULL or not */
+ else if ((start == NULL) || (end == NULL)) {
+ IOH_LOG(KERN_ERR,
+ "ioh_set_dma_desc -> NULL pointer parameter.\n");
+ retval = -EINVAL;
+ } else {
+ /* Setting the descriptors. */
+ retval = dma_set_desc(channel, start, end);
+ IOH_DEBUG("ioh_set_dma_desc -> Function dma_set_desc "
+ "returned %d.\n", retval);
+ }
+
+ IOH_DEBUG("Function ioh_set_dma_desc returns %d.\n", retval);
+ return retval;
+}
+EXPORT_SYMBOL(ioh_set_dma_desc);
+
+/*! @ingroup InterfaceLayerAPI
+ @fn int ioh_add_dma_desc(int channel, struct ioh_dma_desc *start,
+ struct ioh_dma_desc *end)
+ @brief Used to append the DMA descriptors for a channel.
+ @remarks Used when a new chain of descriptors is to be appended
+ to the existing chain of descriptors. This
+ function is invoked by functions from other
+ modules. The main tasks performed by this
+ function are:
+ - Verifies whether the obtained parameters are
+ valid, if not suitable error status codes are
+ returned to the called function.
+ - If valid interacts with the HAL API to append
+ the descriptor settings and returns the status
+ code returned by the HAL API.
+ @note This function is accessible by other kernel modules.
+ The following points have to be noted while
+ passing the "start" and "end" pointer of the
+ descriptor.
+ - The address pointer by them should be physical
+ address with valid virtual address.
+ - The space should be alligned and accessible by
+ the DMA hardware.
+ - An easy way to perform this is to allocate the
+ descriptor memory using kmalloc.
+ - The last two bits of the physical address
+ should be suitably set so as to perform suitable
+ action after completion of each descriptor
+ action.
+ - The in-address and out-address within each
+ descriptor should be a valid memory space
+ physical address.
+
+ @param channel [@ref IN] DMA channel number
+ @param start [@ref IN] A pointer to the first descriptor.
+ @param end [@ref IN] A pointer to the last descriptor.
+
+ @return int
+ - @ref IOH_DMA_SUCCESS --> On success.
+ - -EAGAIN --> The device is in suspend mode.
+ - -ENODEV --> Specified DMA channel does not
+ exist.
+ - -EINVAL --> Invalid parameters passed.
+ - -EBUSY --> If DMA Transfer in progress or
+ channel is already enabled.
+ */
+int ioh_add_dma_desc(int channel, struct ioh_dma_desc *start,
+ struct ioh_dma_desc *end)
+{
+ int retval;
+
+ /* Checking whether the device is in suspend mode. */
+ if (1 == ioh_device_suspended) {
+ IOH_LOG(KERN_ERR,
+ "ioh_add_dma_desc -> The device is in suspend "
+ "mode.\n");
+ retval = -EAGAIN;
+ }
+ /* Checking for validity of channel number */
+ else if ((channel >= IOH_DMA_CHANNELS_MAX) || (channel < 0)) {
+ IOH_LOG(KERN_ERR, "ioh_add_dma_desc -> Invalid Channel "
+ "number : %d", channel);
+ retval = -ENODEV;
+ }
+ /* Checking whether channel is not allocated. */
+ else if (ioh_dma_channel_table[channel].ch_alloced == (u16) 0) {
+ IOH_LOG(KERN_ERR,
+ "ioh_add_dma_desc -> Channel not alloctaed.\n");
+ retval = -EINVAL;
+ }
+ /* Checking whether the channel is enabled. */
+ else if (ioh_dma_channel_info[channel].bChEnabled == 1) {
+ IOH_LOG(KERN_ERR,
+ "ioh_add_dma_desc -> Channel already enabled.\n");
+ retval = -EBUSY;
+ }
+ /* Checking whether the mode is other than SCATTER_GATHER. */
+ else if (ioh_dma_channel_info[channel].DMATransferMode !=
+ (u16) DMA_SCATTER_GATHER_MODE) {
+ IOH_LOG(KERN_ERR,
+ "ioh_add_dma_desc -> Current mode id is not "
+ "SCATTER_GATHER.\n");
+ retval = -EINVAL;
+ }
+ /* Checking if descriptor field of the channel is set earlier. */
+ else if ((ioh_dma_channel_info[channel].pHeadOfList == NULL) ||
+ (ioh_dma_channel_info[channel].pTailOfList == NULL)) {
+ IOH_LOG(KERN_ERR, "ioh_add_dma_desc -> Descriptor list not "
+ "set earlier.\n");
+ retval = -EINVAL;
+ }
+ /* Checking whether start and end pointers are NULL or not */
+ else if ((start == NULL) || (end == NULL)) {
+ IOH_LOG(KERN_ERR,
+ "ioh_add_dma_desc -> NULL pointer parameter.\n");
+ retval = -EINVAL;
+ } else {
+ /* Appending the descriptors to the available list. */
+ retval = dma_add_desc(channel, start, end);
+ IOH_DEBUG
+ ("ioh_add_dma_desc -> Function dma_add_desc returned %d.\n",
+ retval);
+ }
+
+ IOH_DEBUG("Function ioh_add_dma_desc returns %d.\n", retval);
+ return retval;
+}
+EXPORT_SYMBOL(ioh_add_dma_desc);
+
+/*! @ingroup InterfaceLayerAPI
+ @fn int ioh_enable_dma(int channel)
+ @brief Used to enable a DMA channel.
+ @remarks Used when a DMA channel has to be enabled. This
+ function is invoked by functions from other
+ kernel modules. The main tasks performed by this
+ function are:
+ - Verifies whether the obtained parameters are
+ valid, if not suitable error status codes are
+ returned to the called function.
+ - If valid interacts with the HAL API to enable
+ the channel and returns the status code returned
+ by the HAL API.
+ @note This function is accessible by other kernel modules.
+
+ @param channel [@ref IN] DMA channel number .
+
+ @return int
+ - @ref IOH_DMA_SUCCESS --> On success.
+ - -EAGAIN --> Device is in suspend mode.
+ - -ENODEV --> Specified DMA channel does
+ not exist.
+ - -EINVAL --> Specified channel is not
+ allocated.
+ - -EBUSY --> DMA Transfer already in
+ progress or channel is
+ already enabled.
+ */
+int ioh_enable_dma(int channel)
+{
+ int retval;
+
+ /* Checking whether the device is in suspend mode. */
+ if (ioh_device_suspended == 1) {
+ IOH_LOG(KERN_ERR, "ioh_enable_dma -> Device is in suspend "
+ "mode.\n");
+ retval = -EAGAIN;
+ }
+ /* Checking for validity of channel number */
+ else if ((channel >= IOH_DMA_CHANNELS_MAX) || (channel < 0)) {
+ IOH_LOG(KERN_ERR, "ioh_enable_dma ->Invalid Channel number "
+ ": %d.\n", channel);
+ retval = -ENODEV;
+ }
+ /* Checking whether channel is allocated. */
+ else if (ioh_dma_channel_table[channel].ch_alloced == (u16) 0) {
+ IOH_LOG(KERN_ERR, "ioh_enable_dma -> Channel not allocated.\n");
+ retval = -EINVAL;
+ }
+ /* Checking whether the channel is already enabled. */
+ else if (ioh_dma_channel_info[channel].bChEnabled == 1) {
+ IOH_LOG(KERN_ERR,
+ "ioh_enable_dma -> Channel already enabled.\n");
+ retval = -EBUSY;
+ } else {
+ /* Enabling the channel. */
+ retval = dma_enable_ch(channel);
+ IOH_DEBUG("ioh_enable_dma -> Function dma_enable_ch returned "
+ "%d.\n", retval);
+ }
+
+ IOH_DEBUG("Function ioh_enable_dma returns %d.\n", retval);
+ return retval;
+}
+EXPORT_SYMBOL(ioh_enable_dma);
+
+/*! @ingroup InterfaceLayerAPI
+ @fn int ioh_disable_dma(int channel)
+ @brief Used to disable a DMA channel.
+ @remarks Used when a DMA channel has to be disabled. This
+ function is invoked by functions from other
+ kernel modules. The main tasks performed by this
+ function are:
+ - Verifies whether the obtained parameters are
+ valid, if not suitable error status codes are
+ returned to the called function.
+ - If valid interacts with the HAL API to disable
+ the channel and returns the status code returned
+ by the HAL API.
+ @note This function is accessible by other kernel modules.
+
+ @param channel [@ref IN] DMA channel number .
+
+ @return int
+ - @ref IOH_DMA_SUCCESS --> On success.
+ - -ENODEV --> Specified DMA channel does not
+ exist.
+ - -EINVAL --> Specified channel is not allocated.
+
+ */
+int ioh_disable_dma(int channel)
+{
+ int retval;
+ u16 statusInfo;
+
+ /* Checking whether the device is in suspend mode. */
+ if (ioh_device_suspended == 1) {
+ IOH_LOG(KERN_ERR, "ioh_disable_dma -> Device is in "
+ "suspend mode.\n");
+ retval = -EAGAIN;
+ }
+ /* Checking for validity of channel number. */
+ else if ((channel >= IOH_DMA_CHANNELS_MAX) || (channel < 0)) {
+ IOH_LOG(KERN_ERR, "ioh_disable_dma -> Invalid Channel "
+ "number : %d", channel);
+ retval = -ENODEV;
+ }
+ /* Checking whether channel is allocated. */
+ else if (ioh_dma_channel_table[channel].ch_alloced == (u16) 0) {
+ IOH_LOG(KERN_ERR, "ioh_disable_dma -> Channel not "
+ "allocated.\n");
+ retval = -EINVAL;
+ }
+ /* Check whether channel is already disabled. */
+ else if (ioh_dma_channel_info[channel].bChEnabled == (u16) 0) {
+ retval = IOH_DMA_SUCCESS;
+ } else {
+ u32 counter = COUNTER_LIMIT;
+
+ /* Wait for any DMA for certain interval transfer to end
+ before disabling the channel */
+ do {
+ get_dma_status(channel, &statusInfo);
+ } while ((counter--) && (statusInfo != (u16) DMA_STATUS_IDLE));
+
+ /* Disabling the channel. */
+ retval = dma_disable_ch(channel);
+ IOH_DEBUG("ioh_disable_dma -> Function dma_disable_ch "
+ "returned %d.\n", retval);
+
+ }
+
+ IOH_DEBUG("Function ioh_disable_dma returns " "%d.\n", retval);
+ return retval;
+}
+EXPORT_SYMBOL(ioh_disable_dma);
+
+/*! @ingroup InterfaceLayerAPI
+ @fn int ioh_dma_set_callback(int channel,
+ void (*ioh_dma_cbr)( int value,unsigned long data1),
+ unsigned long data)
+ @brief Used to set the callback function for particular DMA channel.
+ @remarks Sets the callback function to be called when an
+ interrupt occurs. This function is invoked by
+ functions from other kernel modules. The main
+ tasks performed by this function are:
+ - Verifies whether the obtained parameters are
+ valid, if not suitable error status codes are
+ returned to the called function.
+ - If valid interacts with the HAL API to set the
+ callback function settings and returns the
+ status code returned by the HAL API.
+ @note This function is accessible by other kernel modules.
+
+ @param channel [@ref IN] DMA channel number .
+ @param ioh_dma_cbr [@ref IN] Pointer to the call-back
+ function.
+
+ @return int
+ - @ref IOH_DMA_SUCCESS --> On success.
+ - -EAGAIN --> Device is in suspend mode.
+ - -EINVAL --> Parameter passed is invalid.
+ - -ENODEV --> Specified DMA channel does
+ not exist.
+ - -EBUSY --> If the channel is already
+ enabled.
+ */
+int ioh_dma_set_callback(int channel,
+ void (*ioh_dma_cbr) (int value, unsigned long data1),
+ unsigned long data)
+{
+ int retval;
+
+ /* Checking whether the device is in suspend mode. */
+ if (ioh_device_suspended == 1) {
+ IOH_LOG(KERN_ERR, "ioh_dma_set_callback -> The device is "
+ "in suspend mode.\n");
+ retval = -EAGAIN;
+ }
+ /* Checking for validity of channel number */
+ else if ((channel >= IOH_DMA_CHANNELS_MAX) || (channel < 0)) {
+ IOH_LOG(KERN_ERR, "ioh_dma_set_callback -> Invalid Channel "
+ "number : %d.\n", channel);
+ retval = -ENODEV;
+ }
+ /* Checking whether channel is not allocated. */
+ else if (ioh_dma_channel_table[channel].ch_alloced == (u16) 0) {
+ IOH_LOG(KERN_ERR,
+ "ioh_dma_set_callback -> Channel not allocated.\n");
+ retval = -EINVAL;
+ }
+ /* Checking whether the channel is already enabled. */
+ else if (ioh_dma_channel_info[channel].bChEnabled == 1) {
+ IOH_LOG(KERN_ERR,
+ "ioh_dma_set_callback -> Channel already enabled.\n");
+ retval = -EBUSY;
+ }
+ /* Checking whether function pointer is NULL or not */
+ else if (ioh_dma_cbr == NULL) {
+ IOH_LOG(KERN_ERR,
+ "ioh_dma_set_callback -> NULL pointer parameter.\n");
+ retval = -EINVAL;
+ } else {
+ /* Setting the callback. */
+ dma_set_callback(channel, ioh_dma_cbr, data);
+ IOH_DEBUG
+ ("ioh_dma_set_callback -> Function dma_set_callback invoked"
+ " successfully.\n");
+
+ retval = IOH_DMA_SUCCESS;
+ }
+
+ IOH_DEBUG("Function ioh_dma_set_callback " "returns %d.\n", retval);
+ return retval;
+}
+EXPORT_SYMBOL(ioh_dma_set_callback);
+
+/*! @ingroup InterfaceLayer
+ @fn int ioh_set_dma_priority (int channel, int priority)
+ @brief Sets the priority of the DMA channel.
+ @remarks Sets the priority that has to be assigned for a
+ particular channel. This function is invoked by
+ functions from other kernel modules. The main
+ tasks performed by this function are:
+ - Verifies whether the obtained parameters are
+ valid, if not, suitable error status codes are
+ returned to the called function.
+ - If valid, interacts with the HAL API to set
+ the DMA channel priority settings and returns
+ the status code returned by the HAL API.
+ @note This function is accessible by other kernel modules.
+
+ @param channel [@ref IN] DMA channel number.
+ @param priority [@ref IN] Priority to be set for the
+ DMA channel.
+
+ @return int
+ - @ref IOH_DMA_SUCCESS --> On success.
+ - -EAGAIN --> Device is in suspend mode.
+ - -EINVAL --> Parameter passed is invalid.
+ - -EBUSY --> If channel is in use.
+ - -ENODEV --> Specified DMA channel does not
+ exist.
+
+ */
+int ioh_set_dma_priority(int channel, int priority)
+{
+ int retval;
+
+ /* Checking whether the device is in suspend mode. */
+ if (ioh_device_suspended == 1) {
+ IOH_LOG(KERN_ERR, "ioh_set_dma_priority -> The device is "
+ "in suspend mode.\n");
+ retval = -EAGAIN;
+ }
+ /* Checking for validity of channel number */
+ else if ((channel >= IOH_DMA_CHANNELS_MAX) || (channel < 0)) {
+ IOH_LOG(KERN_ERR, "ioh_set_dma_priority -> Invalid Channel "
+ "number : %d", channel);
+ retval = -ENODEV;
+ }
+ /* Checking whether channel is not allocated. */
+ else if (ioh_dma_channel_table[channel].ch_alloced == (u16) 0) {
+ IOH_LOG(KERN_ERR, "ioh_set_dma_priority -> Channel not "
+ "allocated.\n");
+ retval = -EINVAL;
+ }
+ /* Checking whether the device is enabled. */
+ else if (ioh_dma_channel_info[channel].bChEnabled == 1) {
+ IOH_LOG(KERN_ERR, "ioh_set_dma_priority -> Channel already "
+ "enabled.\n");
+ retval = -EBUSY;
+ }
+ /* Check for validity of priority value */
+ else if ((priority > 3) || (priority < 0)) {
+ IOH_LOG(KERN_ERR, "ioh_set_dma_priority -> Invalid value "
+ "priority (%d)", priority);
+ retval = -EINVAL;
+ } else {
+ retval = dma_set_priority(channel, priority);
+ IOH_DEBUG("ioh_set_dma_priority -> Function dma_set_priority "
+ "returns %d.\n", retval);
+ }
+
+ IOH_DEBUG("Function ioh_set_dma_priority returns " "%d.\n", retval);
+ return retval;
+}
+EXPORT_SYMBOL(ioh_set_dma_priority);
+
+/*! @ingroup InterfaceLayerAPI
+ @fn int ioh_dma_direct_start (int channel)
+ @brief Used to initiate a DMA transfer.
+ @remarks Generates the DMA request to begin DMA transfer
+ on a particular channel. This function is
+ invoked by functions from other kernel modules.
+ The main tasks performed by this function are:
+ - Verifies whether the obtained parameters are
+ valid, if not suitable error status codes are
+ returned to the called function.
+ - If valid interacts with the HAL API to
+ initiate the DMA process and returns the status
+ code returned by the HAL API.
+ @note This function is accessible by other kernel modules.
+
+ @param channel DMA channel number.
+
+ @return int
+ - @ref IOH_DMA_SUCCESS --> On success.
+ - -EAGAIN --> Device is in suspend mode.
+ - -EBUSY --> Specified DMA channel is not idle.
+ - -ENODEV --> Specified DMA channel does not
+ exist.
+ - -EINVAL --> Specified channel is not allocated.
+
+ */
+int ioh_dma_direct_start(int channel)
+{
+ int retval = 0;
+
+ /* Checking whether the device is in suspend mode. */
+ if (ioh_device_suspended == 1) {
+ IOH_LOG(KERN_ERR, "ioh_dma_direct_start -> The device is in "
+ "suspend mode.\n");
+ retval = -EAGAIN;
+ }
+ /* Checking for validity of channel number */
+ else if ((channel >= IOH_DMA_CHANNELS_MAX) || (channel < 0)) {
+ IOH_LOG(KERN_ERR, "ioh_dma_direct_start -> Invalid Channel "
+ "number : %d.\n", channel);
+ retval = -ENODEV;
+ }
+ /* Checking whether channel is reserved or not */
+ else if (ioh_dma_channel_table[channel].ch_alloced == (u16) 0) {
+ IOH_LOG(KERN_ERR, "ioh_dma_direct_start -> Channel not "
+ "allocated.\n");
+ retval = -EINVAL;
+ }
+ /* Checking whether the device is not enabled. */
+ else if (ioh_dma_channel_info[channel].bChEnabled == 0) {
+ IOH_LOG(KERN_ERR, "ioh_dma_direct_start -> Channel not "
+ "enabled.\n");
+ retval = -EBUSY;
+ } else {
+ /* Initiating the DMA transfer */
+ retval = dma_direct_start(channel);
+ IOH_DEBUG("ioh_dma_direct_start -> Function dma_direct_start "
+ "returned %d.\n", retval);
+ }
+
+ IOH_DEBUG("Function ioh_dma_direct_start returns " "%d.\n", retval);
+ return retval;
+}
+EXPORT_SYMBOL(ioh_dma_direct_start);
--- /dev/null
+++ b/drivers/dma/pch_dma/pch_dma_main.h
@@ -0,0 +1,264 @@
+/**
+ * @file ioh_dma_main.h
+ *
+ * @brief
+ * This file declares the structures & data types used by the
+ * IOH_DMA driver.
+ *
+ * @version 0.90
+ * @section
+ * 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; version 2 of the License.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * <hr>
+ */
+
+/*
+ * History:
+ * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD.
+ * All rights reserved.
+ *
+ * created:
+ * WIPRO 03/07/2009
+ * modified:
+ * WIPRO 08/14/2009
+ *
+ */
+
+#ifndef __IOH_DMA_H__
+#define __IOH_DMA_H__
+
+/*! @ingroup InterfaceLayer
+ @def DMA_ONE_SHOT_MODE
+ @brief Constant used to denote the mode as ONE_SHOT.
+ @note This constant is used by other modules to make the
+ DMA module aware of the mode it requires.
+*/
+#define DMA_ONE_SHOT_MODE (0x2U)
+
+/*! @ingroup InterfaceLayer
+ @def DMA_SCATTER_GATHER_MODE
+ @brief Constant used to denote the mode as SCATTER_GATHER.
+ @note This constant is used by other modules to make the
+ DMA module aware of the mode it requires.
+*/
+#define DMA_SCATTER_GATHER_MODE (0x1U)
+
+/*! @ingroup InterfaceLayer
+ @def IOH_DMA_SIZE_TYPE_8BIT
+ @brief Constant used to denote the access size as 8BIT.
+ @note This constant is used by other modules to make the
+ DMA module aware of the access size it requires.
+*/
+#define IOH_DMA_SIZE_TYPE_8BIT ((0x3U << 12))
+
+/*! @ingroup InterfaceLayer
+ @def IOH_DMA_SIZE_TYPE_16BIT
+ @brief Constant used to denote the access size as 16BIT.
+ @note This constant is used by other modules to make the
+ DMA module aware of the access size it requires.
+*/
+#define IOH_DMA_SIZE_TYPE_16BIT ((0x2U << 12))
+
+/*! @ingroup InterfaceLayer
+ @def IOH_DMA_SIZE_TYPE_32BIT
+ @brief Constant used to denote the access size as 32BIT.
+ @note This constant is used by other modules to make the
+ DMA module aware of the access size it requires.
+*/
+#define IOH_DMA_SIZE_TYPE_32BIT (0x0U)
+
+/*! @ingroup InterfaceLayer
+ @def IOH_DMA_DIR_OUT_TO_IN
+ @brief Constant used to denote the transfer direction as
+ OUT_TO_IN.
+ @note This constant is used by other modules to make the
+ DMA module aware of the transfer direction it
+ requires.
+*/
+#define IOH_DMA_DIR_OUT_TO_IN (0x4)
+
+/*! @ingroup InterfaceLayer
+ @def IOH_DMA_DIR_IN_TO_OUT
+ @brief Constant used to denote the transfer direction as
+ IN_TO_OUT.
+ @note This constant is used by other modules to make the
+ DMA module aware of the transfer direction it
+ requires.
+*/
+#define IOH_DMA_DIR_IN_TO_OUT (0x0)
+
+/*! @ingroup InterfaceLayer
+ @def IOH_DMA_END
+ @brief Constant used to denote the transfer status as ACCESS
+ @note This constant is used by DMA modules to make the
+ other module aware that the DMA operation ended
+ normally.
+*/
+#define IOH_DMA_END (0)
+
+/*! @ingroup InterfaceLayer
+ @def IOH_DMA_ABORT
+ @brief Constant used to denote the transfer status as ACCESS
+ @note This constant is used by DMA modules to make the
+ other module aware that the DMA abort has
+ occurred.
+*/
+#define IOH_DMA_ABORT (-1)
+
+/* Bits to be sit as LSB2 bits of descriptor address. */
+/*! @ingroup InterfaceLayer
+ @def DMA_DESC_END_WITH_INTERRUPT
+ @brief Mask value for modifying the next descriptor
+ address, so that the descriptor end with
+ interrupt.
+*/
+#define DMA_DESC_END_WITH_INTERRUPT (0x00000001UL)
+
+/*! @ingroup InterfaceLayer
+ @def DMA_DESC_FOLLOW_WITH_INTERRUPT
+ @brief Mask value for modifying the next descriptor
+ address, so that the descriptor follow with
+ interrupt.
+
+*/
+#define DMA_DESC_FOLLOW_WITH_INTERRUPT (0x00000003UL)
+
+/*! @ingroup InterfaceLayer
+ @def DMA_DESC_END_WITHOUT_INTERRUPT
+ @brief Mask value for modifying the next descriptor
+ address, so that the descriptor end without
+ interrupt.
+*/
+#define DMA_DESC_END_WITHOUT_INTERRUPT (0x00000000UL)
+
+/*! @ingroup InterfaceLayer
+ @def DMA_DESC_FOLLOW_WITHOUT_INTERRUPT
+ @brief Mask value for modifying the next descriptor
+ address, so that the descriptor follow without
+ interrupt.
+
+*/
+#define DMA_DESC_FOLLOW_WITHOUT_INTERRUPT (0x00000002UL)
+
+/*! @ingroup InterfaceLayer
+ @def IOH_DMA_8BIT_COUNT_MAX
+ @brief The maximun transfer count that can be set for
+ a 8Bit Access.
+
+*/
+#define IOH_DMA_8BIT_COUNT_MAX (0x3FF)
+
+/*! @ingroup InterfaceLayer
+ @def IOH_DMA_16BIT_COUNT_MAX
+ @brief The maximun transfer count that can be set for
+ a 16Bit Access.
+
+*/
+#define IOH_DMA_16BIT_COUNT_MAX (0x3FF)
+
+/*! @ingroup InterfaceLayer
+ @def IOH_DMA_32BIT_COUNT_MAX
+ @brief The maximun transfer count that can be set for
+ a 32Bit Access.
+
+*/
+#define IOH_DMA_32BIT_COUNT_MAX (0x7FF)
+
+/*! @ingroup DMA
+ @def IOH_DMA_SUCCESS
+ @brief The value indicating a success.
+*/
+#define IOH_DMA_SUCCESS (0)
+
+/*! @ingroup DMA
+ @def IOH_DMA_FAILURE
+ @brief The value indicating a failure.
+*/
+#define IOH_DMA_FAILURE (-1)
+
+/*! @ingroup InterfaceLayerFacilitators
+ @enum ioh_channel_request_id
+ @brief Constant used to denote the channel request type.
+ @note These constants are used by other modules to make the
+ DMA module aware of the channel type it
+ requires.
+*/
+enum ioh_channel_request_id {
+ IOH_DMA_TX_DATA_REQ0 = 1, /**< Transmission channel 0. */
+ IOH_DMA_RX_DATA_REQ0, /**< Reception channel 0. */
+ IOH_DMA_TX_DATA_REQ1, /**< Transmission channel 1. */
+ IOH_DMA_RX_DATA_REQ1, /**< Reception channel 1. */
+ IOH_DMA_TX_DATA_REQ2, /**< Transmission channel 2. */
+ IOH_DMA_RX_DATA_REQ2, /**< Reception channel 2. */
+ IOH_DMA_TX_DATA_REQ3, /**< Transmission channel 3. */
+ IOH_DMA_RX_DATA_REQ3, /**< Reception channel 3. */
+ IOH_DMA_TX_DATA_REQ4, /**< Transmission channel 4. */
+ IOH_DMA_RX_DATA_REQ4, /**< Reception channel 4. */
+ IOH_DMA_TX_DATA_REQ5, /**< Transmission channel 5. */
+ IOH_DMA_RX_DATA_REQ5 /**< Reception channel 5. */
+};
+
+/*! @ingroup InterfaceLayerFacilitators
+ @struct __ioh_dma_mode_param
+ @brief Format for specifying the mode characteristics of
+ a channel.
+ @note This structure is used by other modules to make the
+ DMA module aware of the channel mode
+ characteristics.
+*/
+
+struct ioh_dma_mode_param {
+ u16 TransferDirection; /**< Direction of Transfer(IN to OUT or OUT to
+ IN). */
+ u16 DMASizeType; /**< Type of DMA Transfer size (8bit, 16bit or
+ 32bit). */
+ u16 DMATransferMode; /**< Mode of Transfer (ONE_SHOT_MODE or
+ SCATTER_GATHER_MODE). */
+};
+
+/*! @ingroup InterfaceLayerFacilitators
+ @struct __ioh_dma_desc
+ @brief Format for specifying the descriptors.
+ @note This structure is used by other modules to make the
+ DMA module aware of the channel descriptors in
+ SCATTER_GATHER_MODE.
+*/
+
+struct ioh_dma_desc {
+ u32 insideAddress; /**< Inside address. */
+ u32 outsideAddress; /**< Outside address. */
+ u32 size; /**< Size. */
+ u32 nextDesc; /**< Next Descriptor address.*/
+};
+
+extern int ioh_request_dma(struct pci_dev *dev, int dreq);
+extern int ioh_free_dma(int channel);
+extern int ioh_set_dma_mode(int channel, struct ioh_dma_mode_param stModeParam);
+extern int ioh_set_dma_addr(int channel, unsigned int iaddr,
+ unsigned int oaddr);
+extern int ioh_set_dma_count(int channel, unsigned int count);
+extern int ioh_set_dma_desc(int channel, struct ioh_dma_desc *start,
+ struct ioh_dma_desc *end);
+extern int ioh_add_dma_desc(int channel, struct ioh_dma_desc *start,
+ struct ioh_dma_desc *end);
+extern int ioh_enable_dma(int channel);
+extern int ioh_disable_dma(int channel);
+extern int ioh_dma_set_callback(int channel,
+ void (*ioh_dma_cbr) (int value,
+ unsigned long data1),
+ unsigned long data);
+extern int ioh_set_dma_priority(int channel, int priority);
+extern int ioh_dma_direct_start(int channel);
+
+#endif
--- /dev/null
+++ b/drivers/dma/pch_dma/pch_dma_pci.c
@@ -0,0 +1,694 @@
+/**
+ * @file ioh_dma_pci.c
+ *
+ * @brief
+ * This file defines the methods of IOH_DMA_CONTROLLER driver.
+ *
+ * @version 0.90
+ * @section
+ * 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; version 2 of the License.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * <hr>
+ */
+
+/*
+ * History:
+ * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD.
+ * All rights reserved.
+ *
+ * created:
+ * WIPRO 03/07/2009
+ * modified:
+ * WIPRO 08/14/2009
+ *
+ */
+
+/* inclusion of system specific header files. */
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+
+/* inclusion of module specific header files. */
+#include "pch_debug.h"
+#include "pch_dma_pci.h"
+#include "pch_dma_hal.h"
+
+MODULE_LICENSE("GPL");
+
+/* Global variables */
+
+/*! @ingroup Global
+ @var MODULE_NAME
+ @brief The module name variable.
+ @remarks This variable is used as the module name.
+*/
+#define MODULE_NAME "pch_dma"
+/*! @ingroup Global
+ @var ioh_device_suspended
+ @brief Device suspend flag.
+ @remarks This variable is used as a flag variable
+ for denoting the device suspend state.
+ @see
+ - ioh_dma_suspend
+ - ioh_dma_resume
+*/
+unsigned char ioh_device_suspended;
+
+/*! @ingroup Global
+ @var ioh_device_lock
+ @brief Device lock variable.
+ @remarks This variable is used as a lock variable
+ for accessing the DMA channel.
+ @see
+ - ioh_request_dma
+*/
+spinlock_t ioh_device_lock;
+
+/*! @ingroup Global
+ @var ioh_dma_devices
+ @brief Stores the details of the DMA devices.
+ @remarks This variable is the instance of the structure
+ struct ioh_dma_devices, which includes fields
+ for storing the details of the detected DMA
+ devices. This variable facilitates easy transfer
+ of information among the different functions of
+ the DMA module.
+*/
+struct ioh_dma_devices ioh_dma_devices[IOH_DMA_MAX_DEVS];
+
+/*! @ingroup PCILayerFacilitators
+ @struct ioh_dma_pcidev_id
+ @brief The structure for specifying the supported
+ device IDs to the PCI Kernel subsystem.
+ @remarks This structure is the instance of the
+ kernel provided structure pci_device_id,
+ which is used to store the PCI devices
+ Vendor and Device ID. This structure is
+ used during the registration of the DMA module
+ as PCI Driver. This structure makes the Kernel
+ aware of the PCI devices supported by this
+ module.
+
+ @see
+ - ioh_dma_controller_driver
+*/
+
+static const struct pci_device_id ioh_dma_pcidev_id[] __devinitdata = {
+ /* 4 Channel DMA device IDs */
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOH1_DMA4_0)},
+
+ /* 8 Channel DMA device IDs */
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOH1_DMA8_0)},
+
+ /* 12 Channel DMA device IDs */
+ {}
+};
+
+/* Function prototypes */
+static int __devinit ioh_dma_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id);
+static void __devexit ioh_dma_remove(struct pci_dev *pdev);
+static int ioh_dma_suspend(struct pci_dev *pdev, pm_message_t state);
+static int ioh_dma_resume(struct pci_dev *pdev);
+static __init int ioh_dma_pci_init(void);
+static __exit void ioh_dma_pci_exit(void);
+static inline u32 get_dev_type(u32 devid);
+
+/*! @ingroup PCILayer
+ @def IOH_INVALID_DEVICE
+ @brief The return value of @ref get_dev_type for invalid
+ device type.
+
+ @see
+ - get_dev_type
+*/
+#define IOH_INVALID_DEVICE (0xFFFF)
+
+/*! @ingroup InternalFunction
+ @fn static inline u32 get_dev_type (u32 devid)
+ @brief Returns the IOH device type for given PCI device id.
+ @remarks This function returns the type of the detected DMA
+ device. The type specifies the number of DMA
+ channels contained within the detected device.
+ The tasks performed by this function include:
+ - Matches the PCI device ID passed to it with a
+ set of known device IDs.
+ - If a match is found it returns a constant
+ which indicates the device type (number of DMA
+ channels) within the device.
+ - If no match is found it returns @ref
+ IOH_INVALID_DEVICE.
+
+ @param devid [@ref IN] The device ID to be verified.
+
+ @return u32
+ - Values other than @ref IOH_INVALID_DEVICE
+ --> Detected device is valid and
+ supported.
+ - @ref IOH_INVALID_DEVICE --> Invalid device
+ detected.
+
+ @see
+ - ioh_dma_probe
+
+*/
+static inline u32 get_dev_type(u32 devid)
+{
+ u32 dev_type;
+
+ switch (devid) {
+ case PCI_DEVICE_ID_INTEL_IOH1_DMA4_0:
+ dev_type = IOH_DMA_4CH0;
+ break;
+
+ case PCI_DEVICE_ID_INTEL_IOH1_DMA8_0:
+ dev_type = IOH_DMA_8CH0;
+ break;
+
+ default:
+ IOH_LOG(KERN_ERR, "get_dev_type -> Unknown PCI "
+ "device 0x%x\n", devid);
+ dev_type = IOH_INVALID_DEVICE;
+ break;
+
+ }
+
+ IOH_DEBUG("Function get_dev_type returns %x.\n", dev_type);
+ return dev_type;
+}
+
+/*! @ingroup PCILayerAPI
+ @fn static int __devinit ioh_dma_probe(struct pci_dev* pdev,
+ const struct pci_device_id* id)
+ @brief Implements the probe function for the PCI driver.
+ @remarks This function acts as the probe function for
+ the PCI driver. The PCI core will be invoking
+ this function once it determines that this
+ driver is suitable for handling a particular
+ hardware. The main tasks performed by this
+ function are:
+ - Confirms whether the detected device is
+ supported by the driver.
+ - Enables the PCi device.
+ - Attains the device specific resources and
+ store it for further use.
+ - Enables the device and registers the handler
+ for handling the device interrupts.
+ - Initializes the device specific data
+ structures.
+
+ @param pdev [@ref INOUT] Reference to the pci_device
+ structure.
+ @param id [@ref IN] Reference to the pci_device_id
+ for which this device matches.
+
+ @return int
+ - @ref IOH_DMA_SUCCESS --> On success.
+ - -EIO --> pci_enable_device error status code.
+ - -EBUSY: --> pci_request_regions/request_irq
+ error status code.
+ - -EINVAL --> pci_enable_device/request_irq error
+ status code/invalid device ID.
+ - -ENOMEM --> request_irq/pci_iomap error status
+ code.
+ - -ENOSYS --> request_irq error status code.
+
+ @see
+ - ioh_dma_controller_driver
+ */
+static int __devinit ioh_dma_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ static unsigned int ioh_dma_dcount;
+ int retval;
+ u32 dev_type;
+ u32 base_addr = 0;
+ u8 device_enabled = 0;
+ u8 regions_requested = 0;
+ u8 irq_registered = 0;
+
+ do {
+ /* Getting the internally used device ID of the detected
+ device. */
+ dev_type = get_dev_type(id->device);
+ /* If invalid device. */
+ if ((IOH_INVALID_DEVICE == dev_type)) {
+ IOH_LOG(KERN_ERR, "ioh_dma_probe -> Invalid device ID "
+ "%x.\n", id->device);
+ retval = -EINVAL;
+ break;
+ }
+ IOH_DEBUG("ioh_dma_probe -> Valid device ID detected %x.\n",
+ id->device);
+
+ /* Enabling the detected device */
+ retval = pci_enable_device(pdev);
+ if (0 != retval) {
+ IOH_LOG(KERN_ERR,
+ "ioh_dma_probe -> Function pci_enable_device "
+ "failed, returned %d.\n", retval);
+ break;
+ }
+ device_enabled = 1;
+ IOH_DEBUG
+ ("ioh_dma_probe -> Function pci_enable_device invoked "
+ "successfully returned %d.\n", retval);
+
+ pci_set_master(pdev);
+ IOH_DEBUG("ioh_dma_probe -> Function pci_set_master invoked "
+ "successfully.\n");
+
+ /* Requesting the PCI device regions. */
+ retval = pci_request_regions(pdev, MODULE_NAME);
+ if (0 != retval) {
+ IOH_LOG(KERN_ERR,
+ "ioh_dma_probe -> Function pci_request_regions "
+ "failed, returned %d.\n", retval);
+ break;
+ }
+ regions_requested = 1;
+ IOH_DEBUG
+ ("ioh_dma_probe -> Function pci_request_regions invoked "
+ "successfully returned %d.\n", retval);
+
+ /* Remapping the device space to kernel space. */
+ /* Wipro 1/13/2010 Use Mem BAR */
+ base_addr = (u32) pci_iomap(pdev, 1, 0);
+ if (0 == base_addr) {
+ IOH_LOG(KERN_ERR,
+ "ioh_dma_probe -> Function pci_iomap failed "
+ "returned %x.\n", base_addr);
+ retval = -ENOMEM;
+ break;
+ }
+ IOH_DEBUG
+ ("ioh_dma_probe -> Function pci_iomap invoked successfully."
+ "\n");
+
+ /* Filling in the details within the device structure. */
+ ioh_dma_devices[ioh_dma_dcount].dev_typ = dev_type;
+ ioh_dma_devices[ioh_dma_dcount].base_addr = base_addr;
+ ioh_dma_devices[ioh_dma_dcount].dev = (void *)pdev;
+
+ /* Registering the interrupt handler. */
+ retval =
+ request_irq(pdev->irq, dma_interrupt, IRQF_SHARED,
+ MODULE_NAME, &ioh_dma_devices[ioh_dma_dcount]);
+ if (0 != retval) {
+ IOH_LOG(KERN_ERR,
+ "ioh_dma_probe -> Function request_irq failed, "
+ "returned %d.\n", retval);
+
+ break;
+ }
+ irq_registered = 1;
+ IOH_DEBUG
+ ("ioh_dma_probe -> Function request_irq invoked "
+ "successfully returned %d.\n", retval);
+
+ /* Initializing the DMA device. */
+ dma_init(base_addr, dev_type);
+ IOH_DEBUG
+ ("ioh_dma_probe -> Function dma_init invoked successfully."
+ "\n");
+
+ /* Stroing the device structure reference for further use. */
+ pci_set_drvdata(pdev, &ioh_dma_devices[ioh_dma_dcount]);
+
+ /* Initializing the suspend flag and lock variable. */
+ if (0 == ioh_dma_dcount) { /* Initialize only once. */
+ ioh_device_suspended = 0;
+ spin_lock_init(&ioh_device_lock);
+ }
+
+ /* Incrementing the device structure index. */
+ ioh_dma_dcount++;
+
+ /* Probe successful. */
+ retval = IOH_DMA_SUCCESS;
+ IOH_DEBUG("ioh_dma_probe -> Probe successful.\n");
+
+ } while (0);
+
+ if (IOH_DMA_SUCCESS != retval) {
+ /* Un-registering the interrupt handler. */
+ if (1 == irq_registered) {
+ free_irq(pdev->irq, &ioh_dma_devices[ioh_dma_dcount]);
+ IOH_DEBUG("ioh_dma_probe -> Function free_irq invoked "
+ "successfully.\n");
+ }
+ /* Unmapping the remapped region. */
+ if (0 != base_addr) {
+ pci_iounmap(pdev, (void *)base_addr);
+ IOH_DEBUG
+ ("ioh_dma_probe -> Function pci_iounmap invoked "
+ "successfully.\n");
+ }
+ /* Releasing the requested regions. */
+ if (1 == regions_requested) {
+ pci_release_regions(pdev);
+ IOH_DEBUG
+ ("ioh_dma_probe -> Function pci_release_regions "
+ "invoked successfully.\n");
+ }
+ /* Disabling the device. */
+ if (1 == device_enabled) {
+ pci_disable_device(pdev);
+ IOH_DEBUG
+ ("ioh_dma_probe -> Function pci_disable_device "
+ "invoked successfully.\n");
+ }
+
+ IOH_DEBUG("ioh_dma_probe -> Probe failed.\n");
+ }
+
+ IOH_DEBUG("Function ioh_dma_probe returns %d.\n", retval);
+ return retval;
+}
+
+/*! @ingroup PCILayerAPI
+ @fn static void __devexit ioh_dma_remove(struct pci_dev* pdev)
+ @brief Implements the remove function for the PCi driver.
+ @remarks This function is invoked by the PCI subsystem of the
+ Kernel when the DMA device is removed or the
+ module is unloaded.
+ It de-initializes and releases all the resources
+ attained during device detection. The main tasks
+ performed by this function are:
+ - De-initializes the DMA device.
+ - De-initializes the device specific data
+ structures.
+ - Releases all the resources attained during the
+ device detection phase.
+
+ @param pdev [@ref INOUT] Reference to the pci_device structure.
+
+ @return None.
+
+ @see
+ - ioh_dma_controller_driver
+ */
+static void __devexit ioh_dma_remove(struct pci_dev *pdev)
+{
+ struct ioh_dma_devices *dev;
+
+ /* Getting the driver data. */
+ dev = pci_get_drvdata(pdev);
+ /* Re-setting the driver data. */
+ pci_set_drvdata(pdev, NULL);
+
+ /* De-initializing the device. */
+ dma_exit(dev->dev_typ);
+ IOH_DEBUG("ioh_dma_remove -> Function dma_exit invoked "
+ "successfully.\n");
+
+ /* Un-registering the interrupt handler. */
+ free_irq(pdev->irq, dev);
+ IOH_DEBUG("ioh_dma_remove -> Function free_irq invoked "
+ "successfully.\n");
+
+ /* Un-mapping the remapped memory address. */
+ pci_iounmap(pdev, (void *)dev->base_addr);
+ dev->base_addr = 0;
+ IOH_DEBUG("ioh_dma_remove -> Function pci_iounmap invoked "
+ "successfully.\n");
+
+ /* Releasing the requested regions. */
+ pci_release_regions(pdev);
+ IOH_DEBUG("ioh_dma_remove -> Function pci_release_regions "
+ "invoked successfully.\n");
+
+ /* Disabling the device. */
+ pci_disable_device(pdev);
+ IOH_DEBUG("ioh_dma_remove -> Function pci_disable_device "
+ "invoked successfully.\n");
+
+ IOH_DEBUG("Function ioh_dma_remove invoked "
+ "successfully for device %x.\n", pdev->device);
+}
+
+#ifdef CONFIG_PM
+/*! @ingroup PCILayerAPI
+ @fn static int ioh_dma_suspend(struct pci_dev* pdev,
+ pm_message_t state)
+ @brief Implements the suspend function for the pci_driver.
+ @remarks This function is used as the suspend function of the PCI
+ Driver.
+ The PCI core will be invoking this function once
+ it receives a suspend event from the PM layer.
+ The main tasks performed by this functions are:
+ - Prepares the device so that it can enter the
+ suspend state by saving the current state.
+ - Disables all the DMA channels and the
+ associated interrupts.
+ - Changes the power state of the device to low
+ power state.
+
+ @param pdev [@ref INOUT] Reference to the pci_device structure.
+ @param state [@ref IN] The state of the device.
+
+ @return int
+ - @ref IOH_DMA_SUCCESS --> On success.
+ - -ENOMEM --> pci_save_state error status code.
+
+ @see
+ - ioh_dma_controller_driver
+ */
+static int ioh_dma_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ int retval;
+ struct ioh_dma_devices *dev;
+
+ /* Setting flag for denoting Suspension. */
+ ioh_device_suspended = 1;
+
+ /* Getting the driver data. */
+ dev = pci_get_drvdata(pdev);
+
+ /* Saving the current state of the device. */
+ retval = pci_save_state(pdev);
+ if (retval == 0) {
+ IOH_DEBUG("ioh_dma_suspend -> Function pci_save_state invoked "
+ "successfully (returned %d).\n", retval);
+
+ /* De-initializing the device for suspension. */
+ dma_exit(dev->dev_typ);
+ IOH_DEBUG("ioh_dma_suspend -> Function dma_exit invoked "
+ "successfully.\n");
+
+ /* Disabling the wake-up feature. */
+ pci_enable_wake(pdev, PCI_D3hot, 0);
+ IOH_DEBUG("ioh_dma_suspend -> Function pci_enable_wake "
+ "invoked successfully.\n");
+
+ /* Setting the device to new state. */
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+ IOH_DEBUG("ioh_dma_suspend -> Function pci_set_power_state "
+ "invoked successfully.\n");
+
+ /* Disabling the device. */
+ pci_disable_device(pdev);
+ IOH_DEBUG("ioh_dma_suspend -> Function pci_disable_device "
+ "invoked successfully.\n");
+
+ retval = IOH_DMA_SUCCESS;
+ IOH_DEBUG("ioh_dma_suspend -> Suspension successful for "
+ "the device %x.\n", pdev->device);
+ } else {
+ IOH_LOG(KERN_ERR,
+ "ioh_dma_suspend -> Function pci_save_state failed"
+ "returned %d.\n", retval);
+
+ /* De-setting the flag on Suspend failure. */
+ ioh_device_suspended = 0;
+
+ IOH_DEBUG("ioh_dma_suspend -> Suspension un-successful for "
+ "the device %x.\n", pdev->device);
+ }
+
+ IOH_DEBUG("Function ioh_dma_suspend returns %d.\n", retval);
+ return retval;
+}
+
+/*! @ingroup PCILayerAPI
+ @fn static int ioh_dma_resume(struct pci_dev* pdev)
+ @brief Implements the resume function for the pci_driver.
+ @remarks This function is used as the resume function of the
+ PCI driver. The PCI core will be invoking this
+ function once it receives a resume event from
+ the PM layer. The main tasks performed by this
+ function are:
+ - Restores the power state of the device to
+ normal state.
+ - Enables the device so that it returns to its
+ normal state.
+
+ @param pdev [@ref INOUT] Pointer to the pci_device
+ structure.
+
+ @return int
+ - @ref IOH_DMA_SUCCESS --> On success.
+ - -EIO --> pci_enable_device error status code.
+ - -EINVAL --> pci_enable_device .
+
+ @see
+ - ioh_dma_controller_driver
+
+ */
+static int ioh_dma_resume(struct pci_dev *pdev)
+{
+ int retval;
+
+ /* Setting the device to normal power state. */
+ (void)pci_set_power_state(pdev, PCI_D0);
+ IOH_DEBUG("ioh_dma_resume -> Function pci_set_power_state invoked "
+ "successfully.\n");
+
+ /* Restoring the device state. */
+ (void)pci_restore_state(pdev);
+ IOH_DEBUG("ioh_dma_resume -> Function pci_restore_state invoked "
+ "successfully.\n");
+
+ /* Enabling the device. */
+ retval = pci_enable_device(pdev);
+
+ if (0 == retval) {
+ IOH_DEBUG("ioh_dma_resume -> Function pci_enable_device "
+ "invoked successfully returned %d.\n", retval);
+
+ pci_set_master(pdev);
+ IOH_DEBUG("ioh_dma_resume -> Function pci_set_master invoked "
+ "successfully.\n");
+
+ (void)pci_enable_wake(pdev, PCI_D3hot, 0);
+ IOH_DEBUG("ioh_dma_resume -> Function pci_enable_wake invoked "
+ "successfully.\n");
+
+ retval = IOH_DMA_SUCCESS;
+
+ /* De-setting the suspend flag to denote resumption
+ successful. */
+ ioh_device_suspended = 0;
+
+ IOH_DEBUG("ioh_dma_resume -> Resume successful for the "
+ "device %x.\n", pdev->device);
+ } else {
+ IOH_LOG(KERN_ERR,
+ "ioh_dma_resume -> Function pci_enable_device failed "
+ "returned %d.\n", retval);
+
+ IOH_DEBUG("ioh_dma_resume -> Resume failed for the device "
+ "%x.\n", pdev->device);
+ }
+
+ IOH_DEBUG("Function ioh_dma_resume returns %d.\n", retval);
+ return retval;
+}
+#endif
+
+/*! @ingroup PCILayerFacilitators
+ @struct ioh_dma_controller_driver
+ @brief Used for registering the PCI driver functionalities.
+ @remarks This is an instance of the structure pci_driver which
+ stores references to the PCI Driver
+ functionalities.
+ It is used during PCI driver registration for
+ interfacing the DMA module functionalities with
+ that of the Kernel subsystem.
+
+ @see
+ - ioh_dma_pci_init
+ - ioh_dma_pci_exit
+*/
+
+static struct pci_driver ioh_dma_controller_driver = {
+ .name = "ioh_dma", /**< Name of the module. */
+ .id_table = ioh_dma_pcidev_id, /**< The list of supported devices. */
+ .probe = ioh_dma_probe, /**< The probe function. */
+ .remove = __devexit_p(ioh_dma_remove), /**< The remove function. */
+#ifdef CONFIG_PM
+ .suspend = ioh_dma_suspend, /**< The suspend function. */
+ .resume = ioh_dma_resume /**< The resume function. */
+#endif
+};
+
+/*! @ingroup PCILayerAPI
+ @fn static __init int ioh_dma_pci_init(void)
+ @brief Module initialization routine.
+ @remarks This function is invoked when the module is
+ loaded. The main tasks performed by this
+ function are:
+ - Initializes the module.
+ - Initializes the local structures
+ and registers the module as PCI Driver
+ with the kernel subsystem.
+
+ @return int
+ - @ref IOH_DMA_SUCCESS --> On success.
+ - -EEXIST --> pci_register_driver error status
+ code.
+ - -EINVAL --> pci_register_driver error status
+ code.
+ - -ENOMEM --> pci_register_driver error status
+ code.
+
+ */
+static __init int ioh_dma_pci_init(void)
+{
+ int retval;
+
+ /* Registering the module as PCI Driver. */
+ retval = pci_register_driver(&ioh_dma_controller_driver);
+
+ if (0 == retval) {
+ IOH_DEBUG
+ ("ioh_dma_pci_init -> Function pci_register_driver invoked "
+ "successfully returned %d.\n", retval);
+
+ retval = IOH_DMA_SUCCESS;
+ } else {
+ IOH_LOG(KERN_ERR,
+ "ioh_dma_pci_init -> Function pci_register_driver "
+ "failed returned %d.\n", retval);
+ }
+
+ IOH_DEBUG("Function ioh_dma_pci_init returns %d.\n", retval);
+ return retval;
+}
+
+/*! @ingroup PCILayerAPI
+ @fn static __exit void ioh_dma_pci_exit(void)
+ @brief Module exit handler.
+ @remarks Kernel subsystem will be invoking this routine
+ once the module gets unloaded. The main tasks
+ performed by this function are:
+ - Un-registers the PCI driver.
+ - Unloads the module.
+
+ @return None.
+ */
+static __exit void ioh_dma_pci_exit(void)
+{
+ /* Un-registering the module as PCI Driver. */
+ pci_unregister_driver(&ioh_dma_controller_driver);
+ IOH_DEBUG("ioh_dma_pci_exit -> Function pci_unregister_driver "
+ "invoked successfully.\n");
+
+ IOH_DEBUG("Function ioh_dma_pci_exit invoked successfully.\n");
+}
+
+MODULE_DEVICE_TABLE(pci, ioh_dma_pcidev_id);
+module_init(ioh_dma_pci_init);
+module_exit(ioh_dma_pci_exit);
--- /dev/null
+++ b/drivers/dma/pch_dma/pch_dma_pci.h
@@ -0,0 +1,74 @@
+/**
+ * @file ioh_dma_pci.h
+ *
+ * @brief
+ * This file declares the constants & functions used by the
+ * IOH_DMA_CONTROLLER driver.
+ *
+ * @version 0.90
+ * @section
+ * 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; version 2 of the License.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * <hr>
+ */
+
+/*
+ * History:
+ * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD.
+ * All rights reserved.
+ *
+ * created:
+ * WIPRO 03/07/2009
+ * modified:
+ * WIPRO 08/14/2009
+ *
+ */
+
+#ifndef __IOH_DMA_PCI_H__
+#define __IOH_DMA_PCI_H__
+
+/*! @ingroup PCILayer
+ @def PCI_DEVICE_ID_INTEL_IOH1_DMA4_0
+ @brief The Device ID of one of the DMA device
+ with 4 channels used for the GE devices.
+ @note This is used for registering the DMA module
+ with the PCI subsystem of the Kernel, so that
+ the module is loaded when the required device
+ is detected.
+
+ @see
+ - ioh_dma_pcidev_id
+ - get_dev_type
+*/
+#define PCI_DEVICE_ID_INTEL_IOH1_DMA4_0 (0x8815UL)
+
+/*! @ingroup PCILayer
+ @def PCI_DEVICE_ID_DMA8_0_CONTROLLER
+ @brief The Device ID of one of the DMA device
+ with 8 channels used for the GE devcies.
+ @note This is used for registering the DMA module
+ with the PCI subsystem of the Kernel, so that
+ the module is loaded when the required device
+ is detected.
+
+ @see
+ - ioh_dma_pcidev_id
+ - get_dev_type
+*/
+#define PCI_DEVICE_ID_INTEL_IOH1_DMA8_0 (0x8810UL)
+
+extern unsigned char ioh_device_suspended; /* The device suspend flag. */
+extern spinlock_t ioh_device_lock; /* The device lock variable. */
+
+#endif