From 239a368d5715d8f5b7733f9400339c2350c49369 Mon Sep 17 00:00:00 2001 From: Saul Wold Date: Fri, 24 Sep 2010 15:36:24 -0700 Subject: netbook: Correct netbook build by moving netbook configuration from moblin to meta Signed-off-by: Saul Wold --- .../linux-2.6.34-pch-dma.patch | 4133 ++++++++++++++++++++ 1 file changed, 4133 insertions(+) create mode 100644 meta/recipes-kernel/linux/linux-netbook-2.6.33.2/linux-2.6.34-pch-dma.patch (limited to 'meta/recipes-kernel/linux/linux-netbook-2.6.33.2/linux-2.6.34-pch-dma.patch') diff --git a/meta/recipes-kernel/linux/linux-netbook-2.6.33.2/linux-2.6.34-pch-dma.patch b/meta/recipes-kernel/linux/linux-netbook-2.6.33.2/linux-2.6.34-pch-dma.patch new file mode 100644 index 000000000..e3fddb2df --- /dev/null +++ b/meta/recipes-kernel/linux/linux-netbook-2.6.33.2/linux-2.6.34-pch-dma.patch @@ -0,0 +1,4133 @@ +--- + 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. ++ * ++ *
++ */ ++ ++/* ++ * History: ++ * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD. ++ * All rights reserved. ++ * ++ * created: ++ * WIPRO 03/07/2009 ++ * modified: ++ * WIPRO 08/14/2009 ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#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. ++ * ++ *
++ */ ++ ++/* ++ * 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 ++#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. ++ * ++ *
++ */ ++ ++/* ++ * History: ++ * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD. ++ * All rights reserved. ++ * ++ * created: ++ * WIPRO 03/07/2009 ++ * modified: ++ * WIPRO 08/14/2009 ++ * ++ */ ++ ++#include ++#include ++#include ++ ++#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. ++ * ++ *
++ */ ++ ++/* ++ * 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. ++ * ++ *
++ */ ++ ++/* ++ * 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 ++#include ++#include ++#include ++ ++/* 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. ++ * ++ *
++ */ ++ ++/* ++ * 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 -- cgit v1.2.3