[PATCH] Topcliff DMA: Add the DMA driver [2/4]

Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
From: Masayuki Ohtake
Date: Tuesday, April 27, 2010 - 4:01 am

+  - pch_enable_dma
+  - pch_disable_dma
+  - pch_set_dma_priority
+  - pch_dma_direct_start
+
+  */
+
+void get_dma_status(int channel, u16 *pDMAStatus)
+{
+ u32 status_val;
+ u32 base_address;
+ u16 ch;
+
+ ch = pch_dma_channel_table[channel].channel;
+ base_address = pch_dma_channel_table[channel].base;
+
+ if (ch < 8) {
+  status_val = PCH_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 = PCH_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));
+ }
+
+ PCH_DEBUG("Function get_dma_status invoked successfully.\n");
+}
+
+/*! @ingroup HALLayerAPI
+ @fn  int dma_set_desc(int channel,
+    struct pch_dma_desc *start,
+    struct pch_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
+    pch_dma_channel_info structure to the value of
+    the argument start.
+    - Set the pTailOfList field of the @ref
+    pch_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
+   - pch_set_dma_desc
+ */
+
+int dma_set_desc(int channel, struct pch_dma_desc *start,
+   struct pch_dma_desc *end)
+{
+ pch_dma_channel_info[channel].pHeadOfList = start;
+ pch_dma_channel_info[channel].pTailOfList = end;
+
+ PCH_DEBUG("Function dma_set_desc returns %d.\n", PCH_DMA_SUCCESS);
+ return PCH_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
+    pch_dma_channel_info[index]
+
+ @param  index [@ref IN] Index in the
+     pch_dma_channel_table
+
+ @return None
+
+ @see
+   - dma_request_ch
+ */
+void get_free_ch(int index)
+{
+ memset((void *)&pch_dma_channel_info[index], 0,
+        sizeof(struct pch_dma_controller_info));
+ PCH_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 pch_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
+   - pch_request_dma
+ */
+
+int dma_request_ch(u32 req_dev_id, int dreq)
+{
+ int retval;
+ int i;
+
+ for (i = 0; i < PCH_DMA_CHANNELS_MAX; i++) {
+  if ((pch_dma_channel_table[i].req_device_id == req_dev_id) &&
+      (pch_dma_channel_table[i].request_signal == dreq)) {
+   if ((1 == pch_dma_channel_table[i].ch_found) &&
+       (0 == pch_dma_channel_table[i].ch_alloced)) {
+    get_free_ch(i);
+    PCH_DEBUG
+        ("dma_request_ch -> Function get_free_ch "
+         "invoked successfully.\n");
+    pch_dma_channel_table[i].ch_alloced = 1;
+    retval = i;
+
+    break;
+   }
+  }
+ }
+
+ if (PCH_DMA_CHANNELS_MAX == i) {
+  retval = -EBUSY;
+  PCH_LOG(KERN_ERR, "dma_request_ch ->  Not able to allocate "
+   "channel.\n");
+ }
+
+ PCH_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
+     PCH_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 pch_dma_channel_info and @ref
+    pch_dma_channel_table and return @ref
+    PCH_DMA_SUCCESS.
+
+ @param  channel [@ref IN] DMA channel number to be freed.
+
+ @return int
+   - @ref PCH_DMA_SUCCESS --> On success.
+
+ @see
+   - pch_free_dma
+ */
+
+int dma_free_ch(int channel)
+{
+ int retval;
+
+ if (pch_dma_channel_table[channel].ch_alloced == (u16) 0) {
+  PCH_DEBUG("dma_free_ch -> Channel is already free\n");
+  retval = PCH_DMA_SUCCESS;
+ } else {
+  /* To stop any active transfer on DMA, disable DMA */
+  (void)dma_disable_ch(channel);
+  PCH_DEBUG("dma_free_ch -> Function dma_disable_ch invoked "
+     "successfully.\n");
+
+  (void)dma_enable_disable_interrupt(channel,
+         PCH_DMA_INTERRUPT_DISABLE);
+  PCH_DEBUG
+      ("dma_free_ch -> Function dma_enable_disable_interrupt "
+       "invoked successfully.\n");
+
+  pch_dma_channel_table[channel].ch_alloced = 0;
+
+  retval = PCH_DMA_SUCCESS;
+ }
+
+ PCH_DEBUG("Function dma_free_ch returns %d.\n", PCH_DMA_SUCCESS);
+ return retval;
+}
diff -urN linux-2.6.33.1/drivers/dma/pch_dma/pch_dma_hal.h
topcliff-2.6.33.1/drivers/dma/pch_dma/pch_dma_hal.h
--- linux-2.6.33.1/drivers/dma/pch_dma/pch_dma_hal.h 1970-01-01
09:00:00.000000000 +0900
+++ topcliff-2.6.33.1/drivers/dma/pch_dma/pch_dma_hal.h 2010-04-27
11:46:20.000000000 +0900
@@ -0,0 +1,592 @@
+/**
+ * @file pch_dma_hal.h
+ *
+ * @brief
+ *  This file declares the structures & data types used by the HAL
+ *  functions of PCH_DMA_CONTROLLER driver.
+ *
+ * @version 0.90
+ * @section
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307,
USA.
+ *
+ * <hr>
+ */
+
+/*
+ * History:
+ * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD.
+ *
+ *
+ * created:
+ * OKISEMI 04/14/2010
+ *
+ */
+
+#ifndef __PCH_DMA_HAL_H__
+#define __PCH_DMA_HAL_H__
+
+#include <linux/interrupt.h>
+#include "pch_dma_main.h"
+
+/*!
+ @defgroup DMA
+*/
+
+/*! @defgroup Global
+ @ingroup DMA
+ @brief  This group contains all the global data
+    structures used by the DMA module.
+*/
+
+/*! defgroup InternalFunction
+ @ingroup DMA
+ @brief  This group contains all the function which
+    are used by other APIs for performing some
+    small tasks for facilitating the logic
+    of the driver.
+*/
+
+/*! @defgroup PCILayer
+ @ingroup DMA
+ @brief  This group contains all the utilities
+    used to interface the DMA module with
+    the PCI subsystem of the Kernel.
+*/
+
+/*! @defgroup InterfaceLayer
+ @ingroup DMA
+ @brief  This group contains all the utilities
+    used by the DMA module to interface with
+    the other modules.
+*/
+
+/*! @defgroup HALLayer
+ @ingroup DMA
+ @brief  This group contains all the utilities
+    used to DMA module to interact with the
+    hardware.
+*/
+
+/*! @defgroup PCILayerAPI
+ @ingroup PCILayer
+ @brief  This group contains the APIs used to
+    interface the DMA module with the PCI
+    subsystem of the Kernel.
+*/
+
+/*! @defgroup PCILayerFacilitators
+ @ingroup PCILayer
+ @brief  This group contains the data structures
+    used by the PCILayerAPIs for their
+    functioning.
+*/
+
+/*! @defgroup HALLayerAPI
+ @ingroup HALLayer
+ @brief  This group contains the APIs used to
+    communicate with the hardware.
+*/
+
+/*! @defgroup HALLayerFacilitators
+ @ingroup HALLayer
+ @brief  This group contains the data structures
+    used to communicate with the hardware.
+*/
+
+/*! @defgroup InterfaceLayerAPI
+ @ingroup InterfaceLayer
+ @brief  This group contains the APIs used by the
+    DMA module to interface with other modules.
+*/
+
+/*! @defgroup InterfaceLayerFacilitators
+ @ingroup InterfaceLayer
+ @brief  This group contains the data structures
+    used by the DMA module to interface with
+    other modules.
+*/
+
+/*** Device specific limitations and properties. ***/
+
+/*! @ingroup DMA
+ @def  PCH_DMA_CHANNELS_MAX
+ @brief  The maximum number of channels allowed
+    in any of the PCH device.
+*/
+#define PCH_DMA_CHANNELS_MAX    (64)
+
+/*! @ingroup DMA
+ @def  PCH_DMA_MAX_DEVS
+ @brief  The no. of DMA devices allowable.
+
+ @see
+  - pch_dma_devices
+*/
+#define PCH_DMA_MAX_DEVS     (4)
+
+/*! @ingroup DMA
+ @def  PCH_DMA_8BIT_SIZE_MAX
+ @brief  The maximum number of transfer size in
+    bytes for a channel if access size is set
+    to 8BIT.
+*/
+#define PCH_DMA_8BIT_SIZE_MAX   (2047)
+
+/*! @ingroup DMA
+ @def  PCH_DMA_16BIT_SIZE_MAX
+ @brief  The maximum number of transfer size in
+    bytes for a channel if access size is set
+    to 16BIT.
+*/
+#define PCH_DMA_16BIT_SIZE_MAX   (4094)
+
+/*! @ingroup DMA
+ @def  PCH_DMA_32BIT_SIZE_MAX
+ @brief  The maximum number of transfer size in
+    bytes for a channel if access size is set
+    to 32BIT.
+*/
+#define PCH_DMA_32BIT_SIZE_MAX   (4096)
+
+/********/
+
+/*** Device IDs of DMA requesting devices. ***/
+/*! @ingroup DMA
+ @def  PCI_DEVICE_ID_PCH_UART0
+ @brief  The deviceID of the PCH GE UART
+    device 0 which can use the DMA features.
+*/
+#define PCI_DEVICE_ID_PCH_UART0      (0x8811)
+
+/*! @ingroup DMA
+ @def  PCI_DEVICE_ID_PCH_UART1
+ @brief  The deviceID of the PCH GE UART
+    device 1 which can use the DMA features.
+*/
+#define PCI_DEVICE_ID_PCH_UART1      (0x8812)
+
+/*! @ingroup DMA
+ @def  PCI_DEVICE_ID_PCH_UART2
+ @brief  The deviceID of the PCH GE UART
+    device 2 which can use the DMA features.
+*/
+#define PCI_DEVICE_ID_PCH_UART2      (0x8813)
+
+/*! @ingroup DMA
+ @def  PCI_DEVICE_ID_PCH_UART3
+ @brief  The deviceID of the PCH GE UART
+    device 3 which can use the DMA features.
+*/
+#define PCI_DEVICE_ID_PCH_UART3      (0x8814)
+
+/*! @ingroup DMA
+ @def  PCI_DEVICE_ID_PCH_SPI
+ @brief  The deviceID of the PCH GE SPI
+    device which can use the DMA features.
+*/
+#define PCI_DEVICE_ID_PCH_SPI (0x8816)
+
+/*** Internal device IDs used for identifing the DMAC . ***/
+/*! @ingroup Global
+ @def  PCH_DMA_4CH0
+ @brief  The device ID for the first DMA device
+    with 4 channels.
+*/
+#define PCH_DMA_4CH0      (0x40)
+
+/*! @ingroup Global
+ @def  PCH_DMA_4CH1
+ @brief  The device ID for the second DMA device
+    with 4 channels.
+*/
+#define PCH_DMA_4CH1      (0x41)
+
+/*! @ingroup Global
+ @def  PCH_DMA_4CH2
+ @brief  The device ID for the third DMA device
+    with 4 channels.
+*/
+#define PCH_DMA_4CH2      (0x42)
+
+/*! @ingroup Global
+ @def  PCH_DMA_4CH3
+ @brief  The device ID for the fourth DMA device
+    with 4 channels.
+*/
+#define PCH_DMA_4CH3      (0x43)
+
+/*! @ingroup Global
+ @def  PCH_DMA_4CH4
+ @brief  The device ID for the fifth DMA device
+    with 4 channels.
+*/
+#define PCH_DMA_4CH4      (0x44)
+
+/*! @ingroup Global
+ @def  PCH_DMA_8CH0
+ @brief  The device ID for the first DMA device
+    with 8 channels.
+*/
+#define PCH_DMA_8CH0      (0x80)
+
+/*! @ingroup Global
+ @def  PCH_DMA_8CH1
+ @brief  The device ID for the second DMA device
+    with 8 channels.
+*/
+#define PCH_DMA_8CH1      (0x81)
+
+/*! @ingroup Global
+ @def  PCH_DMA_8CH2
+ @brief  The device ID for the third DMA device
+    with 8 channels.
+*/
+#define PCH_DMA_8CH2      (0x82)
+
+/*! @ingroup Global
+ @def  PCH_DMA_8CH3
+ @brief  The device ID for the fourth DMA device
+    with 8 channels.
+*/
+#define PCH_DMA_8CH3      (0x83)
+
+/*! @ingroup Global
+ @def  PCH_DMA_12CH0
+ @brief  The device ID for the first DMA device
+    with 12 channels.
+*/
+#define PCH_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  PCH_DMA_INTERRUPT_DISABLE
+ @brief  Constant used to denote disable interrupt.
+*/
+#define PCH_DMA_INTERRUPT_DISABLE   (0)
+
+/*! @ingroup HALLayer
+ @def  PCH_DMA_INTERRUPT_ENABLE
+ @brief  Constant used to denote enable interrupt.
+*/
+#define PCH_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  __pch_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
+  - pch_dma_devices
+*/
+
+struct pch_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  __pch_dma_controller_info_t
+  @brief  Format for storing the details of the
+     DMA channels.
+*/
+
+struct pch_dma_controller_info {
+ u16 DMATransferMode;  /**< DMA Transfer Mode  */
+ u16 bChEnabled;   /**< To know if channel is enabled or
+     not */
+ struct pch_dma_desc *pHeadOfList; /**< Pointer to start
+      descriptor */
+ struct pch_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  pch_dma_channel_alloc_table
+  @brief  Format for storing the details of the
+     allocation details of the DMA channels.
+*/
+
+struct pch_dma_channel_alloc_table {
+ u32 dma_dev_id; /**< The DMA device ID. */
+ enum pch_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 pch_dma_channel_alloc_table
+ pch_dma_channel_table[PCH_DMA_CHANNELS_MAX];
+extern struct pch_dma_controller_info
+ pch_dma_channel_info[PCH_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 pch_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 pch_dma_desc *start,
+   struct pch_dma_desc *end);
+int dma_set_desc(int channel, struct pch_dma_desc *start,
+   struct pch_dma_desc *end);
+void dma_set_callback(int channel,
+        void (*pch_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
diff -urN linux-2.6.33.1/drivers/dma/pch_dma/pch_dma_main.c
topcliff-2.6.33.1/drivers/dma/pch_dma/pch_dma_main.c
--- linux-2.6.33.1/drivers/dma/pch_dma/pch_dma_main.c 1970-01-01
09:00:00.000000000 +0900
+++ topcliff-2.6.33.1/drivers/dma/pch_dma/pch_dma_main.c 2010-04-27
11:46:20.000000000 +0900
@@ -0,0 +1,1024 @@
+/**
+ * @file pch_dma_main.c
+ *
+ * @brief
+ * This file defines the methods of PCH_DMA driver.
+ *
+ *
+ * @version 0.90
+ * @section
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307,
USA.
+ *
+ * <hr>
+ */
+
+/*
+ * History:
+ * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD.
+ *
+ *
+ * created:
+ * OKISEMI 04/14/2010
+ *
+ */
+
+#include <linux/spinlock.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+
+#include "pch_debug.h"
+#include "pch_dma_hal.h"
+#include "pch_dma_pci.h"
+
+
+/*! @ingroup InterfaceLayerAPI
+ @fn  int pch_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 PCH_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 pch_request_dma(struct pci_dev *pdev, int dreq)
+{
+ int retval;
+
+ /* Attaining the lock.  */
+ spin_lock(&pch_device_lock);
+
+ /* If device suspended. */
+ if (1 == pch_device_suspended) {
+  PCH_LOG(KERN_ERR,
+   "pch_request_dma -> Device is in suspend mode.\n");
+  retval = -EAGAIN;
+ }
+ /* Invalid device structure. */
+ else if (NULL == pdev) {
+  PCH_LOG(KERN_ERR,
+   "pch_request_dma -> Obtained device structure "
+   "is NULL.\n");
+  retval = -EINVAL;
+ }
+ /* Invalid request signal. */
+ else if ((dreq < PCH_DMA_TX_DATA_REQ0) ||
+   (dreq > PCH_DMA_RX_DATA_REQ5)) {
+  PCH_LOG(KERN_ERR,
+   "pch_request_dma -> Invalid request signal.\n");
+  retval = -EINVAL;
+ } else {
+  /* Requesting for reserving a DMA channel. */
+  retval = dma_request_ch((u32) (pdev->device), dreq);
+  PCH_DEBUG("pch_request_dma -> Function dma_request_ch returned "
+     "%d.\n", retval);
+ }
+
+ /* Releasing the lock. */
+ spin_unlock(&pch_device_lock);
+
+ PCH_DEBUG("Function pch_request_dma returns %d.\n", retval);
+ return retval;
+}
+EXPORT_SYMBOL(pch_request_dma);
+
+/*! @ingroup InterfaceLayerAPI
+ @fn   int pch_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 PCH_DMA_SUCCESS --> On success.
+   - -EAGAIN  --> Device is in suspend mode.
+   - -ENODEV  --> Specified DMA channel does
+       not exist.
+*/
+int pch_free_dma(int channel)
+{
+ int retval;
+
+ if (1 == pch_device_suspended) {
+  PCH_LOG(KERN_ERR,
+   "pch_free_dma -> Device is in suspend mode.\n");
+  retval = -EAGAIN;
+ } else if ((channel >= PCH_DMA_CHANNELS_MAX) || (channel < 0)) {
+  PCH_LOG(KERN_ERR, "pch_free_dma -> Invalid Channel number: "
+   "%d.\n", channel);
+  retval = -ENODEV;
+ } else {
+  retval = dma_free_ch(channel);
+  PCH_DEBUG("pch_free_dma -> Function dma_free_ch "
+     "returned %d.\n", retval);
+ }
+
+ PCH_DEBUG("Function pch_free_dma returns %d.\n", retval);
+ return retval;
+}
+EXPORT_SYMBOL(pch_free_dma);
+
+/*! @ingroup InterfaceLayerAPI
+ @fn  int pch_set_dma_mode(int channel,struct
+    pch_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 PCH_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 pch_set_dma_mode(int channel, struct pch_dma_mode_param stModeParam)
+{
+ int retval;
+
+ /* Checking if device suspended.                                */
+ if (1 == pch_device_suspended) {
+  PCH_LOG(KERN_ERR,
+   "pch_set_dma_mode -> Device is in suspend mode.\n");
+  retval = -EAGAIN;
+ }
+ /* Checking for validity of channel number.     */
+ else if ((channel >= PCH_DMA_CHANNELS_MAX) || (channel < 0)) {
+  PCH_LOG(KERN_ERR,
+   "pch_set_dma_mode -> Invalid Channel number : " "%d.\n",
+   channel);
+  retval = -ENODEV;
+ }
+ /* Checking whether channel not allocated.              */
+ else if (pch_dma_channel_table[channel].ch_alloced == (u16) 0) {
+  PCH_LOG(KERN_ERR,
+   "pch_set_dma_mode -> Channel not allocated.\n");
+  retval = -EINVAL;
+ }
+ /* Checking if channel already enabled.                 */
+ else if (pch_dma_channel_info[channel].bChEnabled == 1) {
+  PCH_LOG(KERN_ERR,
+   "pch_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)) {
+  PCH_LOG(KERN_ERR,
+   "pch_set_dma_mode -> Invalid DMA Transfer mode.\n");
+  retval = -EINVAL;
+ }
+ /* Checking for validity of Transfer Direction. */
+ else if ((stModeParam.TransferDirection != (u16) PCH_DMA_DIR_OUT_TO_IN)
+   && (stModeParam.TransferDirection !=
+       (u16) PCH_DMA_DIR_IN_TO_OUT)) {
+  PCH_LOG(KERN_ERR,
+   "pch_set_dma_mode -> Invalid DMA Transfer Direction." \
+   "\n");
+  retval = -EINVAL;
+ }
+ /* Checking for validity of Transfer Size Type. */
+ else if ((stModeParam.DMASizeType != (u16) PCH_DMA_SIZE_TYPE_8BIT) &&
+   (stModeParam.DMASizeType != (u16) PCH_DMA_SIZE_TYPE_16BIT) &&
+   (stModeParam.DMASizeType != (u16) PCH_DMA_SIZE_TYPE_32BIT)) {
+  PCH_LOG(KERN_ERR,
+   "pch_set_dma_mode -> Invalid DMA Size Type.\n");
+  retval = -EINVAL;
+ } else {
+  /* Setting the required DMA mode. */
+  retval = dma_set_mode(channel, stModeParam);
+  PCH_DEBUG("pch_set_dma_mode -> Function dma_set_mode "
+     "returned %d.\n", retval);
+ }
+
+ PCH_DEBUG("Function pch_set_dma_mode returns %d.\n", retval);
+ return retval;
+}
+EXPORT_SYMBOL(pch_set_dma_mode);
+
+/*! @ingroup InterfaceLayerAPI
+ @fn  int pch_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 PCH_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 pch_set_dma_addr(int channel, unsigned int iaddr, unsigned int oaddr)
+{
+ int retval;
+
+ /* If the device is in suspend mode. */
+ if (1 == pch_device_suspended) {
+  PCH_LOG(KERN_ERR,
+   "pch_set_dma_addr -> Device is in suspend mode.\n");
+  retval = -EAGAIN;
+ }
+ /* Checking for validity of channel number  */
+ else if ((channel >= PCH_DMA_CHANNELS_MAX) || (channel < 0)) {
+  PCH_LOG(KERN_ERR, "pch_set_dma_addr -> Invalid Channel "
+   "number: %d.\n", channel);
+  retval = -ENODEV;
+ }
+ /* Checking whether channel is not allocated. */
+ else if (pch_dma_channel_table[channel].ch_alloced == (u16) 0) {
+  PCH_LOG(KERN_ERR, "pch_set_dma_addr -> Channel not "
+   "allocated.\n");
+  retval = -EINVAL;
+ }
+ /* Checking whether the channel is already enabled. */
+ else if (pch_dma_channel_info[channel].bChEnabled == 1) {
+  PCH_LOG(KERN_ERR, "pch_set_dma_addr -> Channel already "
+   "enabled.\n");
+  retval = -EBUSY;
+ }
+ /*Checking if addresses specified are NULL or not */
+ else if ((iaddr == 0) || (oaddr == 0)) {
+  PCH_LOG(KERN_ERR, "pch_set_dma_addr -> Invalid address.\n");
+  retval = -EINVAL;
+ }
+ /* Checking if the mode of transfer is  other than ONE_SHOT. */
+ else if (pch_dma_channel_info[channel].DMATransferMode !=
+   (u16) DMA_ONE_SHOT_MODE) {
+  PCH_LOG(KERN_ERR,
+   "pch_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);
+  PCH_DEBUG("pch_set_dma_addr -> Function dma_set_addr invoked "
+     "successfully returned %d.\n", retval);
+ }
+
+ PCH_DEBUG("Function pch_set_dma_addr returns %d.\n", retval);
+ return retval;
+}
+EXPORT_SYMBOL(pch_set_dma_addr);
+
+/*! @ingroup InterfaceLayerAPI
+ @fn  int pch_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 PCH_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 pch_set_dma_count(int channel, unsigned int count)
+{
+ int retval = PCH_DMA_SUCCESS;
+
+ /* Checking if the device is in suspend mode. */
+ if (1 == pch_device_suspended) {
+  PCH_LOG(KERN_ERR, "pch_set_dma_count -> The device is in "
+   "suspend mode.");
+  retval = -EAGAIN;
+ }
+ /* Checking for validity of channel number.  */
+ else if ((channel >= PCH_DMA_CHANNELS_MAX) || (channel < 0)) {
+  PCH_LOG(KERN_ERR, "pch_set_dma_count -> Invalid Channel "
+   "number : %d.\n", channel);
+  retval = -ENODEV;
+ }
+ /* Checking whether channel is not allocated. */
+ else if (pch_dma_channel_table[channel].ch_alloced == (u16) 0) {
+  PCH_LOG(KERN_ERR, "pch_set_dma_count -> Channel is not "
+   "allocated.\n");
+  retval = -EINVAL;
+ }
+ /* Checking whether the channel is enabled. */
+ else if (pch_dma_channel_info[channel].bChEnabled == 1) {
+  PCH_LOG(KERN_ERR, "pch_set_dma_count -> Channel already "
+   "enabled.\n");
+  retval = -EBUSY;
+ }
+ /* Checking if the mode of transfer is other than ONE_SHOT. */
+ else if (pch_dma_channel_info[channel].DMATransferMode !=
+   (u16) DMA_ONE_SHOT_MODE) {
+  PCH_LOG(KERN_ERR,
+   "pch_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 (pch_dma_channel_info[channel].DMAAccessSize) {
+  case PCH_DMA_SIZE_TYPE_8BIT:
+   max_count = PCH_DMA_8BIT_COUNT_MAX;
+   break;
+
+  case PCH_DMA_SIZE_TYPE_16BIT:
+   max_count = PCH_DMA_16BIT_COUNT_MAX;
+   break;
+
+  case PCH_DMA_SIZE_TYPE_32BIT:
+   max_count = PCH_DMA_32BIT_COUNT_MAX;
+   break;
+
+  default:
+   PCH_LOG(KERN_ERR, "pch_set_dma_count -> Invalid Access "
+    "Size.\n");
+   max_count = 0;
+   retval = -EINVAL;
+   break;
+  }
+
+  if ((retval == PCH_DMA_SUCCESS) && (count > max_count)) {
+   PCH_LOG(KERN_ERR,
+    "pch_set_dma_count -> Count (%d) exceeds "
+    "limit the maximum expected count (%d).\n",
+    count, max_count);
+   retval = -EINVAL;
+  }
+ }
+
+ if (PCH_DMA_SUCCESS == retval) {
+  /* Setting the count. */
+  retval = dma_set_count(channel, count);
+  PCH_DEBUG
+      ("pch_set_dma_count -> Function dma_set_count returned "
+       "%d.\n", retval);
+ }
+
+ PCH_DEBUG("Function pch_set_dma_count returns %d.\n", retval);
+ return retval;
+}
+EXPORT_SYMBOL(pch_set_dma_count);
+
+/*! @ingroup InterfaceLayerAPI
+ @fn int pch_set_dma_desc(int channel, struct pch_dma_desc *start,
+   struct pch_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 PCH_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 pch_set_dma_desc(int channel, struct pch_dma_desc *start,

--
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
[PATCH] Topcliff DMA: Add the DMA driver [2/4], Masayuki Ohtake, (Tue Apr 27, 4:01 am)