diff options
Diffstat (limited to 'meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-pch-spi.patch')
-rw-r--r-- | meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-pch-spi.patch | 4377 |
1 files changed, 0 insertions, 4377 deletions
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-pch-spi.patch b/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-pch-spi.patch deleted file mode 100644 index 43129c728..000000000 --- a/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-pch-spi.patch +++ /dev/null @@ -1,4377 +0,0 @@ -From: Masayuki Ohtake <masa-korg@dsn.okisemi.com> -Subject: OKI Semiconductor PCH SPI driver - -This driver implements SPI controls for PCH. - -Signed-off-by: Masayuki Ohtake <masa-korg@dsn.okisemi.com> -Acked-by: Wang Qi <qi.wang@intel.com> - ---- - drivers/spi/Kconfig | 19 ++ - drivers/spi/Makefile | 3 - drivers/spi/pch_common.h | 146 - drivers/spi/pch_spi.h | 389 - drivers/spi/pch_spi_hal.h | 298 - drivers/spi/pch_spi_pci.c | 812 - drivers/spi/pch_debug.h | 60 - drivers/spi/pch_spi_hal.c | 1208 - drivers/spi/pch_spi_main.c | 1323 - drivers/spi/pch_spi_platform_devices.c | 50 - -+++++++++++++++++++++++++++++++ 10 files changed, yyy insertions(+) -diff -urN linux-2.6.33-rc3/drivers/spi/Kconfig topcliff-2.6.33-rc3/drivers/spi/Kconfig ---- linux-2.6.33-rc3/drivers/spi/Kconfig 2010-01-06 09:02:46.000000000 +0900 -+++ topcliff-2.6.33-rc3/drivers/spi/Kconfig 2010-03-06 07:48:16.000000000 +0900 -@@ -53,6 +53,25 @@ - - comment "SPI Master Controller Drivers" - -+config PCH_SPI_PLATFORM_DEVICE -+ bool "PCH SPI Device" -+# depends on PCH_SPI -+ help -+ This registers SPI devices for using with PCH SPI controllers. -+ -+config PCH_SPI_PLATFORM_DEVICE_COUNT -+ int "PCH SPI Bus count" -+ range 1 2 -+ depends on PCH_SPI_PLATFORM_DEVICE -+ help -+ The number of SPI buses/channels supported by the PCH SPI controller. -+ -+config PCH_SPI -+ tristate "PCH SPI Controller" -+ depends on (PCI) && PCH_SPI_PLATFORM_DEVICE -+ help -+ This selects a driver for the PCH SPI Controller -+ - config SPI_ATMEL - tristate "Atmel SPI Controller" - depends on (ARCH_AT91 || AVR32) -diff -urN linux-2.6.33-rc3/drivers/spi/Makefile topcliff-2.6.33-rc3/drivers/spi/Makefile ---- linux-2.6.33-rc3/drivers/spi/Makefile 2010-01-06 09:02:46.000000000 +0900 -+++ topcliff-2.6.33-rc3/drivers/spi/Makefile 2010-03-06 01:52:28.000000000 +0900 -@@ -59,3 +59,6 @@ - - # SPI slave drivers (protocol for that link) - # ... add above this line ... -+obj-$(CONFIG_PCH_SPI) += pch_spi.o -+pch_spi-objs := pch_spi_pci.o pch_spi_hal.o pch_spi_main.o -+obj-$(CONFIG_PCH_SPI_PLATFORM_DEVICE) +=pch_spi_platform_devices.o -diff -urN linux-2.6.33-rc3/drivers/spi/pch_common.h topcliff-2.6.33-rc3/drivers/spi/pch_common.h ---- linux-2.6.33-rc3/drivers/spi/pch_common.h 1970-01-01 09:00:00.000000000 +0900 -+++ topcliff-2.6.33-rc3/drivers/spi/pch_common.h 2010-03-09 05:56:11.000000000 +0900 -@@ -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 -diff -urN linux-2.6.33-rc3/drivers/spi/pch_debug.h topcliff-2.6.33-rc3/drivers/spi/pch_debug.h ---- linux-2.6.33-rc3/drivers/spi/pch_debug.h 1970-01-01 09:00:00.000000000 +0900 -+++ topcliff-2.6.33-rc3/drivers/spi/pch_debug.h 2010-03-09 05:37:47.000000000 +0900 -@@ -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 -diff -urN linux-2.6.33-rc3/drivers/spi/pch_spi.h topcliff-2.6.33-rc3/drivers/spi/pch_spi.h ---- linux-2.6.33-rc3/drivers/spi/pch_spi.h 1970-01-01 09:00:00.000000000 +0900 -+++ topcliff-2.6.33-rc3/drivers/spi/pch_spi.h 2010-03-06 09:01:42.000000000 +0900 -@@ -0,0 +1,389 @@ -+#ifndef __IOH_SPI_H__ -+#define __IOH_SPI_H__ -+/** -+ * @file ioh_spi.h -+ * -+ * @brief This header file contains all macro,structure and function -+ * declarations -+ * for IOH SPI driver. -+ * @version 0.94 -+ * -+ * @par -+ * -- Copyright Notice -- -+ * -+ * @par -+ * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD. -+ * All rights reserved. -+ * -+ * @par -+ * 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. -+ * -+ * @par -+ * -- End of Copyright Notice -- -+ */ -+ -+/*! @defgroup SPI */ -+ -+/*! @defgroup SPI_Global -+@ingroup SPI -+@brief This group describes the global entities within -+ the module. -+@remarks This group includes all the global data structures -+ used within the modules. These are mainly used to -+ store the device related information, so that it can -+ be used by other functions of the modules. -+<hr> -+*/ -+ -+/*! @defgroup SPI_PCILayer -+@ingroup SPI -+@brief This group describes the PCI layer interface -+ functionalities. -+@remarks This group contains the functions and data structures -+ that are used to interface the module with PCI Layer -+ subsystem of the Kernel. -+<hr> -+*/ -+ -+/*! @defgroup SPI_InterfaceLayer -+@ingroup SPI -+@brief This group describes the Driver interface functionalities. -+@remarks This group contains the data structures and functions used -+ to interface the module driver with the kernel subsystem. -+<hr> -+*/ -+ -+/*! @defgroup SPI_HALLayer -+@ingroup SPI -+@brief This group describes the hardware specific functionalities. -+@remarks This group contains the functions and data structures used -+ by the module to communicate with the hardware. These -+ functions are device specific and designed according to the -+ device specifications. -+<hr> -+*/ -+ -+/*! @defgroup SPI_Utilities -+@ingroup SPI -+@brief This group describes the utility functionalities. -+@remarks This group contains the functions and data structures used -+ to assist the other functionalities in their operations. -+<hr> -+*/ -+ -+/*! @defgroup SPI_PCILayerAPI -+@ingroup SPI_PCILayer -+@brief This group contains the API(functions) used as the PCI -+ interface between the Kernel subsystem and the module. -+<hr> -+*/ -+ -+/*! @defgroup SPI_PCILayerFacilitators -+@ingroup SPI_PCILayer -+@brief This group contains the data structures used by the PCI -+ Layer APIs for their functionalities. -+<hr> -+*/ -+ -+/*! @defgroup SPI_InterfaceLayerAPI -+@ingroup SPI_InterfaceLayer -+@brief This group contains the API(functions) used as the Driver -+ interface between the Kernel subsystem and the module. -+<hr> -+*/ -+ -+/*! @defgroup SPI_InterfaceLayerFacilitators -+@ingroup SPI_InterfaceLayer -+@brief This group contains the data structures used by the Driver -+ interface APIs for their functionalities. -+<hr> -+*/ -+ -+/*! @defgroup SPI_HALLayerAPI -+@ingroup SPI_HALLayer -+@brief This group contains the APIs(functions) used to interact with -+ the hardware. These APIs act as an interface between the -+ hardware and the other driver functions. -+<hr> -+*/ -+ -+/*! @defgroup SPI_UtilitiesAPI -+@ingroup SPI_Utilities -+@brief This group contains the APIs(functions) used by other functions -+ in their operations. -+<hr> -+*/ -+ -+#include <linux/wait.h> -+#include <linux/device.h> -+#include <linux/pci.h> -+#include <linux/spi/spi.h> -+#include <linux/workqueue.h> -+ -+/*! @ingroup SPI_Global -+ -+@def STATUS_RUNNING -+ -+@brief SPI channel is running -+ -+@note The status of SPI channel is set to STATUS_RUNNING, -+ once all resources are acquired and initialized from -+ @ref ioh_spi_get_resources -+ -+@see -+ - ioh_spi_get_resources -+ -+<hr> -+*/ -+#define STATUS_RUNNING (1) -+ -+/*! @ingroup SPI_Global -+ -+@def STATUS_EXITING -+ -+@brief SPI device is being removed -+ -+@note The status of SPI channel is set to STATUS_EXITING, -+ when SPI device is being removed. -+ -+@see -+ - ioh_spi_process_messages -+ - ioh_spi_check_request_pending -+ -+<hr> -+*/ -+#define STATUS_EXITING (2) -+ -+/*! @ingroup SPI_Global -+ -+@def DRIVER_NAME -+ -+@brief Name identifier for IOH SPI driver -+ -+@note This name is used while printing debug logs -+ -+<hr> -+*/ -+#define DRIVER_NAME "ioh_spi" -+ -+/*! @ingroup SPI_Global -+ -+@def IOH_SPI_SLEEP_TIME -+ -+@brief Sleep time used in @ref ioh_spi_check_request_pending -+ -+@see -+ - ioh_spi_check_request_pending -+ -+<hr> -+*/ -+#define IOH_SPI_SLEEP_TIME (10) -+ -+/*! @ingroup SPI_Global -+ -+@def IOH_SPI_MAX_DEV -+ -+@brief Denotes Maximum number of SPI channels -+ -+@note This needs to be edited if number of SPI channels -+ change. -+ -+@see -+ - ioh_spi_get_resources -+ - ioh_spi_free_resources -+ - ioh_spi_handler -+ - ioh_spi_check_request_pending -+ - ioh_spi_probe -+ - ioh_spi_suspend -+ - ioh_spi_resume -+ - ioh_spi_remove -+ -+<hr> -+*/ -+#ifdef IOH_DEVICE_GE -+#define IOH_SPI_MAX_DEV (1) -+#else -+#define IOH_SPI_MAX_DEV (1) -+#endif -+ -+/*! @ingroup SPI_Global -+ -+@def IOH_SPI_ADDRESS_SIZE -+ -+@brief Denotes the address range used by one SPI channel. -+ -+@note The base address of a subsequent SPI channel will be -+ (base address of the previous SPI channel) + (IOH_SPI_ADDRESS_SIZE) -+ This needs to be recalculated if any new register is added to a SPI -+ channel. -+ -+@see -+ - ioh_spi_get_resources -+ -+<hr> -+*/ -+#define IOH_SPI_ADDRESS_SIZE (0x20) -+ -+/*structures*/ -+ -+/*! @ingroup SPI_Global -+@struct ioh_spi_data -+@brief Holds the SPI channel specific details -+ -+ This structure holds all the details related to a SPI channel -+ -+ The status of SPI data transfer,the base address are all -+ stored in this structure.The reference to the work queue handler, -+ the SPI message and transmit and receive indices are also stored -+ in this structure. -+ -+@see -+ - ioh_spi_board_data -+ - ioh_spi_select_chip -+ - ioh_spi_deselect_chip -+ - ioh_spi_transfer -+ - ioh_spi_process_messages -+<hr> -+*/ -+ -+struct ioh_spi_data { -+ -+ u32 IORemapAddress; /**< The remapped PCI base address.*/ -+ -+ /**< The SPI master structure that has been registered -+ with the Kernel.*/ -+ struct spi_master *pMaster; -+ -+ struct work_struct Work; /**< Reference to work queue handler*/ -+ -+ /**< Workqueue for carrying out execution of the requests*/ -+ struct workqueue_struct *pWorkQueue; -+ -+ /**< Wait queue for waking up upon receiving an interrupt.*/ -+ wait_queue_head_t Wait; -+ -+ u8 bTransferComplete; /**< Status of SPI Transfer*/ -+ u8 bCurrent_msg_processing; /**< Status flag for message processing*/ -+ -+ spinlock_t Lock; /**< Lock for protecting this structure*/ -+ -+ struct list_head Queue; /**< SPI Message queue*/ -+ u8 Status; /**< Status of the SPI driver.*/ -+ -+ u32 lengthInBpw;/**< Length of data to be transferred in bits per word*/ -+ s8 bTransferActive; /**< Flag showing active transfer*/ -+ u32 TxIndex;/**< Transmit data count; for bookkeeping during transfer*/ -+ u32 RxIndex;/**< Receive data count; for bookkeeping during transfer*/ -+ u16 *pU16TxBuffer; /**< Data to be transmitted*/ -+ u16 *pU16RxBuffer; /**< Received data*/ -+ -+/**< The chip number that this SPI driver currently operates on*/ -+ u8 nCurrentChip; -+ -+ /**< Reference to the current chip that this SPI driver currently -+ operates on*/ -+ struct spi_device *pCurrentChip; -+ -+ /**< The current message that this SPI driver is handling*/ -+ struct spi_message *pCurMsg; -+ -+ /**< The current transfer that this SPI driver is handling*/ -+ struct spi_transfer *pCurTransfer; -+ -+ /**< Reference to the SPI device data structure*/ -+ struct ioh_spi_board_data *pBoardData; -+}; -+ -+/*! @ingroup SPI_Global -+@struct ioh_spi_board_data -+@brief Holds the SPI device specific details -+ -+ This structure holds all the details related to a SPI device. -+ -+ The reference to the pci_dev structure,status of request_irq, -+ pci_request_regions and device suspend are all stored in this structure. -+ -+ This structure also has an array of pointers to ioh_spi_data structures, -+ with each pointer holding the details of one spi channel. -+ -+@see -+ - ioh_spi_data -+ - ioh_spi_check_request_pending -+ - ioh_spi_get_resources -+ - ioh_spi_free_resources -+ - ioh_spi_remove -+ - ioh_spi_suspend -+ - ioh_spi_resume -+ - ioh_spi_probe -+ - ioh_spi_handler -+<hr> -+*/ -+ -+struct ioh_spi_board_data { -+ -+ struct pci_dev *pDev; /**< Reference to the PCI device*/ -+ u8 bIrqRegistered; /**< Status of IRQ registration*/ -+ u8 bRegionRequested; /**< Status of pci_request_regions*/ -+ u8 bSuspended; /**< Status of suspend*/ -+ -+ /**< Reference to SPI channel data structure*/ -+ struct ioh_spi_data *pCtrlData[IOH_SPI_MAX_DEV]; -+}; -+ -+/*function prototypes*/ -+ -+/*! @ingroup SPI_UtilitiesAPI -+@fn ioh_spi_callback( struct ioh_spi_data* pCtrlData) -+@brief Callback function -+*/ -+void ioh_spi_callback(struct ioh_spi_data *pCtrlData); -+ -+/*! @ingroup SPI_UtilitiesAPI -+@fn ioh_spi_free_resources(struct ioh_spi_board_data* pBoardData) -+@brief Frees the resources acquired by IOH SPI driver -+*/ -+void ioh_spi_free_resources(struct ioh_spi_board_data *pBoardData); -+ -+/*! @ingroup SPI_UtilitiesAPI -+@fn ioh_spi_check_request_pending(struct ioh_spi_board_data* pBoardData) -+@brief Checks for any pending SPI transfer request in the queue of pending -+ transfers -+*/ -+int ioh_spi_check_request_pending(struct ioh_spi_board_data *pBoardData); -+ -+/*! @ingroup SPI_UtilitiesAPI -+@fn ioh_spi_get_resources(struct ioh_spi_board_data* pBoardData) -+@brief Acquires the resources for IOH SPI driver -+*/ -+int ioh_spi_get_resources(struct ioh_spi_board_data *pBoardData); -+ -+/*! @ingroup SPI_InterfaceLayerAPI -+@fn ioh_spi_setup(struct spi_device* pSpi) -+@brief Implements the setup routine for IOH SPI driver -+*/ -+int ioh_spi_setup(struct spi_device *pSpi); -+ -+/*! @ingroup SPI_InterfaceLayerAPI -+@fn ioh_spi_transfer(struct spi_device* pSpi,struct spi_message* pMsg) -+@brief Implements the transfer routine for IOH SPI driver -+*/ -+int ioh_spi_transfer(struct spi_device *pSpi, struct spi_message *pMsg); -+ -+/*! @ingroup SPI_InterfaceLayerAPI -+@fn ioh_spi_cleanup(struct spi_device* pSpi) -+@brief Implements the cleanup routine for IOH SPI driver -+*/ -+void ioh_spi_cleanup(struct spi_device *pSpi); -+ -+#endif -diff -urN linux-2.6.33-rc3/drivers/spi/pch_spi_hal.c topcliff-2.6.33-rc3/drivers/spi/pch_spi_hal.c ---- linux-2.6.33-rc3/drivers/spi/pch_spi_hal.c 1970-01-01 09:00:00.000000000 +0900 -+++ topcliff-2.6.33-rc3/drivers/spi/pch_spi_hal.c 2010-03-09 00:41:44.000000000 +0900 -@@ -0,0 +1,1208 @@ -+/** -+ * @file ioh_spi_hal.c -+ * -+ * @brief This file defines the HAL methods . -+ * -+ * @version 0.94 -+ * -+ * @par -+ * -- Copyright Notice -- -+ * -+ * @par -+ * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD. -+ * All rights reserved. -+ * -+ * @par -+ * 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. -+ * -+ * @par -+ * -- End of Copyright Notice -- -+ */ -+ -+#include <linux/io.h> -+#include <linux/interrupt.h> -+#include "pch_common.h" -+#include "pch_debug.h" -+#include "pch_spi.h" -+#include "pch_spi_hal.h" -+ -+/*bit positions in SPCR*/ -+ -+/*! @ingroup SPI_HALLayer -+@def SPCR_SPE_BIT -+@brief SPE bit position in SPCR -+@see -+ - ioh_spi_set_enable -+*/ -+#define SPCR_SPE_BIT (1 << 0) -+ -+/*! @ingroup SPI_HALLayer -+@def SPCR_MSTR_BIT -+@brief MSTR bit position in SPCR -+@see -+ - ioh_spi_set_master_mode -+*/ -+#define SPCR_MSTR_BIT (1 << 1) -+ -+/*! @ingroup SPI_HALLayer -+@def SPCR_LSBF_BIT -+@brief LSBF bit position in SPCR -+@see -+ - ioh_spi_setup_transfer -+*/ -+#define SPCR_LSBF_BIT (1 << 4) -+ -+/*! @ingroup SPI_HALLayer -+@def SPCR_CPHA_BIT -+@brief CPHA bit position in SPCR -+@see -+ - ioh_spi_setup_transfer -+*/ -+#define SPCR_CPHA_BIT (1 << 5) -+ -+/*! @ingroup SPI_HALLayer -+@def SPCR_CPOL_BIT -+@brief CPOL bit position in SPCR -+@see -+ - ioh_spi_setup_transfer -+*/ -+#define SPCR_CPOL_BIT (1 << 6) -+ -+/*! @ingroup SPI_HALLayer -+@def SPCR_TFIE_BIT -+@brief TFIE bit position in SPCR -+@see -+ - ioh_spi_enable_interrupts -+ - ioh_spi_disable_interrupts -+*/ -+#define SPCR_TFIE_BIT (1 << 8) -+ -+/*! @ingroup SPI_HALLayer -+@def SPCR_RFIE_BIT -+@brief RFIE bit position in SPCR -+@see -+ - ioh_spi_enable_interrupts -+ - ioh_spi_disable_interrupts -+*/ -+#define SPCR_RFIE_BIT (1 << 9) -+ -+/*! @ingroup SPI_HALLayer -+@def SPCR_FIE_BIT -+@brief FIE bit position in SPCR -+@see -+ - ioh_spi_enable_interrupts -+ - ioh_spi_disable_interrupts -+*/ -+#define SPCR_FIE_BIT (1 << 10) -+ -+/*! @ingroup SPI_HALLayer -+@def SPCR_ORIE_BIT -+@brief ORIE bit position in SPCR -+@see -+ - ioh_spi_enable_interrupts -+ - ioh_spi_disable_interrupts -+*/ -+#define SPCR_ORIE_BIT (1 << 11) -+ -+/*! @ingroup SPI_HALLayer -+@def SPCR_MDFIE_BIT -+@brief MDFIE bit position in SPCR -+@see -+ - ioh_spi_enable_interrupts -+ - ioh_spi_disable_interrupts -+*/ -+#define SPCR_MDFIE_BIT (1 << 12) -+ -+/*! @ingroup SPI_HALLayer -+@def SPCR_FICLR_BIT -+@brief FICLR bit position in SPCR -+@see -+ - ioh_spi_clear_fifo -+*/ -+#define SPCR_FICLR_BIT (1 << 24) -+ -+/*bit positions in SPSR*/ -+ -+/*! @ingroup SPI_HALLayer -+@def SPSR_TFI_BIT -+@brief TFI bit position in SPCR -+*/ -+#define SPSR_TFI_BIT (1 << 0) -+ -+/*! @ingroup SPI_HALLayer -+@def SPSR_RFI_BIT -+@brief RFI bit position in SPCR -+@see -+ - ioh_spi_handler -+*/ -+#define SPSR_RFI_BIT (1 << 1) -+ -+/*! @ingroup SPI_HALLayer -+@def SPSR_FI_BIT -+@brief FI bit position in SPCR -+@see -+ - ioh_spi_handler -+*/ -+#define SPSR_FI_BIT (1 << 2) -+ -+/*bit positions in SPBRR*/ -+ -+/*! @ingroup SPI_HALLayer -+@def SPBRR_SIZE_BIT -+@brief SIZE bit position in SPCR -+@see -+ - ioh_spi_set_bits_per_word -+*/ -+#define SPBRR_SIZE_BIT (1 << 10) -+ -+/*! @ingroup SPI_HALLayer -+@def SPCR_RFIC_FIELD -+@brief RFIC field in SPCR -+@see -+ - ioh_spi_set_threshold -+*/ -+#define SPCR_RFIC_FIELD (20) -+ -+/*! @ingroup SPI_HALLayer -+@def SPCR_TFIC_FIELD -+@brief TFIC field in SPCR -+@see -+ - ioh_spi_set_threshold -+*/ -+#define SPCR_TFIC_FIELD (16) -+ -+/*! @ingroup SPI_HALLayer -+@def SPSR_INT_BITS -+@brief Mask for all interrupt bits in SPSR -+@see -+ - ioh_spi_reset -+*/ -+#define SPSR_INT_BITS (0x1F) -+ -+/*! @ingroup SPI_HALLayer -+@def MASK_SPBRR_SPBR_BITS -+@brief Mask for clearing SPBR in SPBRR -+@see -+ - ioh_spi_set_baud_rate -+*/ -+#define MASK_SPBRR_SPBR_BITS (0xFFFFFC00) -+ -+/*! @ingroup SPI_HALLayer -+@def MASK_RFIC_SPCR_BITS -+@brief Mask for Rx threshold in SPCR -+@see -+ - ioh_spi_set_threshold -+*/ -+#define MASK_RFIC_SPCR_BITS (0xFF0FFFFF) -+ -+/*! @ingroup SPI_HALLayer -+@def MASK_TFIC_SPCR_BITS -+@brief Mask for Tx threshold in SPCR -+@see -+ - ioh_spi_set_threshold -+*/ -+#define MASK_TFIC_SPCR_BITS (0xFFF0FFF) -+ -+/*! @ingroup SPI_HALLayer -+@def IOH_CLOCK_HZ -+@brief Pclock Freqeuncy -+@see -+ - ioh_spi_set_baud_rate -+*/ -+#ifndef FPGA -+ /*LSI*/ -+#define IOH_CLOCK_HZ (50000000) -+#else -+ /*FPGA*/ -+#define IOH_CLOCK_HZ (62500000) -+#endif -+/*! @ingroup SPI_HALLayer -+@def IOH_SPI_MAX_SPBR -+@brief Maximum value possible for SPBR in SPBRR -+@see -+ - ioh_spi_set_baud_rate -+*/ -+#define IOH_SPI_MAX_SPBR (1023) -+/*global*/ -+/*! @ingroup SPI_HALLayer -+ -+@var ioh_spi_gcbptr -+ -+@brief SPI_Global function pointer to store reference of -+ callback function @ref -+ ioh_spi_callback -+ -+@note The reference of callback function is assigend to this -+ pointer -+ from @ref ioh_spi_probe function by invoking -+ the function @ref ioh_spi_entcb. -+ This global variable is used by the function -+ @ref ioh_spi_hanlder -+ to invoke the callback function. -+ -+@see -+ - ioh_spi_entcb -+ - ioh_spi_handler -+ -+<hr> -+ -+*/ -+static void (*ioh_spi_gcbptr) (struct ioh_spi_data *); -+ -+/*! @ingroup SPI_HALLayerAPI -+ -+@fn ioh_spi_set_master_mode( struct spi_master *master) -+ -+@remarks Sets the MSTR bit in SPCR -+ -+ The main task performed by this method: -+ - Read the content of SPCR register -+ - Set the MSTR bit -+ - Write back the value to SPCR -+ -+@note This function is invoked from @ref ioh_spi_probe to put the IOH SPI -+ device into master mode. -+ -+@param master [@ref IN] Contains reference to struct spi_master -+ -+@retval None -+ -+@see -+ - ioh_spi_probe -+ -+<hr> -+ -+*/ -+void ioh_spi_set_master_mode(struct spi_master *master) -+{ -+ u32 reg_spcr_val; -+ reg_spcr_val = ioh_spi_readreg(master, IOH_SPI_SPCR); -+ IOH_DEBUG("ioh_spi_set_master_mode SPCR content=%x\n", reg_spcr_val); -+ -+ /*sets the second bit of SPCR to 1:master mode */ -+ IOH_SET_BITMSK(reg_spcr_val, SPCR_MSTR_BIT); -+ -+ /*write the value to SPCR register */ -+ ioh_spi_writereg(master, IOH_SPI_SPCR, reg_spcr_val); -+ IOH_DEBUG("ioh_spi_set_master_mode SPCR after setting MSTR bit=%x\n", -+ reg_spcr_val); -+} -+ -+/*! @ingroup SPI_HALLayerAPI -+ -+@fn ioh_spi_set_enable(const struct spi_device *spi, u8 enable) -+ -+@remarks Sets/Resets the SPE bit in SPCR -+ -+ The main tasks performed by this method are: -+ - Read the content of SPCR. -+ - If the enable parameter is true , set the SPE bit. -+ - If the enable paramter is false , clear the SPE bit. -+ - Write back the value to SPCR. -+ -+@note This function is invoked by @ref ioh_spi_process_messages to enable SPI -+ transfer before start of SPI data transfer and to disable SPI data -+ transfer -+ after completion of SPI data transfer. -+ -+@param spi [@ref IN] Contains reference to struct spi_device -+ -+@param enable [@ref IN] -+ To enable SPI transfer enable = true -+ To disable SPI transfer enable = false -+ -+@retval None -+ -+@see -+ - ioh_spi_process_messages -+ -+<hr> -+ -+*/ -+void ioh_spi_set_enable(const struct spi_device *spi, u8 enable) -+{ -+ u32 reg_spcr_val; -+ -+ reg_spcr_val = ioh_spi_readreg(spi->master, IOH_SPI_SPCR); -+ IOH_DEBUG("ioh_spi_set_enable SPCR content=%x\n", reg_spcr_val); -+ -+ if (enable == true) { -+ IOH_DEBUG("ioh_spi_set_enable enable==true\n"); -+ IOH_SET_BITMSK(reg_spcr_val, SPCR_SPE_BIT); -+ } else { -+ IOH_DEBUG("ioh_spi_set_enable enable==false\n"); -+ IOH_CLR_BITMSK(reg_spcr_val, SPCR_SPE_BIT); -+ } -+ -+ ioh_spi_writereg(spi->master, IOH_SPI_SPCR, reg_spcr_val); -+ -+ IOH_DEBUG("ioh_spi_set_enable SPCR content after modifying SPE=%x\n", -+ reg_spcr_val); -+} -+ -+/*! @ingroup SPI_HALLayerAPI -+ -+@fn ioh_spi_handler(int irq, void* dev_id) -+ -+@remarks Interrupt handler -+ -+The main tasks performed by this method are: -+- Check if Corresponding interrupt bits are set in SPSR register. -+- If no, return IRQ_NONE. -+- If yes, read the number of bytes received and write required number of bytes -+according to space available. -+- Update all bookkeeping variables. -+- If bytes/words to be received is less than 16bytes/words,then disable RFI -+and set Rx threshold to 16 bytes/words. -+- If SPI data transfer is completed, invoke the callback function -+@ref ioh_spi_callback to inform the status to @ref ioh_spi_process_messages. -+- Repeat for all SPI channels. -+ -+@note -+This is the interrupt handler for IOH SPI controller driver.This function is -+invoked by the kernel when any interrupt occurs on the interrupt line shared by -+IOH SPI device. The SPI data transfer is initiated by @ref ioh_spi_process_ -+messages,but is carried on by this function.For optimised operation,the HAL -+functions to read and write registers are not used in this function. -+Also register -+address calculation is done once at the beginning to avoid the calculation each -+time while accessing registers. -+ -+@param irq [@ref IN] The interrupt number -+ -+@param dev_id [@ref IN] Contains reference to struct ioh_spi_board_data -+ -+@retval irqreturn_t -+ - IRQ_NONE The interrupt is not ours -+ - IRQ_HANDLED The interrupt has been serviced -+ -+@see -+ - ioh_spi_get_resources -+ - ioh_spi_free_resources -+ - ioh_spi_suspend -+ - ioh_spi_resume -+ -+<hr> -+ -+*/ -+irqreturn_t ioh_spi_handler(int irq, void *dev_id) -+{ -+ /*channel & read/write indices */ -+ int dev, readcnt; -+ -+ /*SPSR content */ -+ u32 reg_spsr_val, reg_spcr_val; -+ -+ /*book keeping variables */ -+ u32 nReadable, TxIndex, RxIndex, lengthInBpw; -+ -+ /*to hold channel data */ -+ -+ struct ioh_spi_data *pCtrlData; -+ -+ /*buffer to store rx/tx data */ -+ u16 *pU16RxBuffer, *pU16TxBuffer; -+ -+ /*register addresses */ -+ u32 SPSR, SPDRR, SPDWR; -+ -+ /*remapped pci base address */ -+ u32 IORemapAddress; -+ -+ irqreturn_t tRetVal = IRQ_NONE; -+ -+ struct ioh_spi_board_data *pBoardData = -+ (struct ioh_spi_board_data *)dev_id; -+ -+ if (pBoardData->bSuspended == true) { -+ IOH_DEBUG("ioh_spi_handler returning due to suspend\n"); -+ } else { -+ for (dev = 0; dev < IOH_SPI_MAX_DEV; dev++) { -+ pCtrlData = pBoardData->pCtrlData[dev]; -+ IORemapAddress = pCtrlData->IORemapAddress; -+ SPSR = IORemapAddress + IOH_SPI_SPSR; -+ -+ reg_spsr_val = IOH_READ_LONG(SPSR); -+ -+ /*Check if the interrupt is for SPI device */ -+ -+ if (reg_spsr_val & (SPSR_FI_BIT | SPSR_RFI_BIT)) { -+ IOH_DEBUG("SPSR in ioh_spi_handler=%x\n", -+ reg_spsr_val); -+ /*clear interrupt */ -+ IOH_WRITE_LONG(reg_spsr_val, SPSR); -+ -+ if (pCtrlData->bTransferActive == true) { -+ RxIndex = pCtrlData->RxIndex; -+ TxIndex = pCtrlData->TxIndex; -+ lengthInBpw = pCtrlData->lengthInBpw; -+ pU16RxBuffer = pCtrlData->pU16RxBuffer; -+ pU16TxBuffer = pCtrlData->pU16TxBuffer; -+ -+ SPDRR = IORemapAddress + IOH_SPI_SPDRR; -+ SPDWR = IORemapAddress + IOH_SPI_SPDWR; -+ -+ nReadable = -+ IOH_SPI_READABLE(reg_spsr_val); -+ -+ for (readcnt = 0; (readcnt < nReadable); -+ readcnt++) { -+ /*read data */ -+ pU16RxBuffer[RxIndex++] = -+ IOH_READ_LONG(SPDRR); -+ /*write data */ -+ -+ if (TxIndex < lengthInBpw) { -+ IOH_WRITE_LONG -+ (pU16TxBuffer -+ [TxIndex++], -+ SPDWR); -+ } -+ } -+ -+ /*disable RFI if not needed */ -+ if ((lengthInBpw - RxIndex) <= -+ IOH_SPI_MAX_FIFO_DEPTH) { -+ IOH_DEBUG -+ ("ioh_spi_handler disabling\ -+ RFI as data remaining=%d\n", -+ (lengthInBpw - RxIndex)); -+ -+ reg_spcr_val = -+ IOH_READ_LONG(IORemapAddress -+ + -+ IOH_SPI_SPCR); -+ -+ /*disable RFI */ -+ IOH_CLR_BITMSK(reg_spcr_val, -+ SPCR_RFIE_BIT); -+ -+ /*reset rx threshold */ -+ reg_spcr_val &= -+ MASK_RFIC_SPCR_BITS; -+ reg_spcr_val |= -+ (IOH_SPI_RX_THOLD_MAX << -+ SPCR_RFIC_FIELD); -+ -+ IOH_WRITE_LONG(IOH_CLR_BITMSK -+ (reg_spcr_val, -+ SPCR_RFIE_BIT), -+ (IORemapAddress + -+ IOH_SPI_SPCR)); -+ } -+ -+ /*update counts */ -+ pCtrlData->TxIndex = TxIndex; -+ -+ pCtrlData->RxIndex = RxIndex; -+ -+ IOH_DEBUG -+ ("ioh_spi_handler RxIndex=%d\n", -+ RxIndex); -+ -+ IOH_DEBUG -+ ("ioh_spi_handler TxIndex=%d\n", -+ TxIndex); -+ -+ IOH_DEBUG -+ ("ioh_spi_handler nWritable=%d\n", -+ (16 - -+ (IOH_SPI_WRITABLE -+ (reg_spsr_val)))); -+ -+ IOH_DEBUG -+ ("ioh_spi_handler nReadable=%d\n", -+ nReadable); -+ } -+ -+ /*if transfer complete interrupt */ -+ if (reg_spsr_val & SPSR_FI_BIT) { -+ IOH_DEBUG -+ ("ioh_spi_handler FI bit in SPSR\ -+ set\n"); -+ -+ /*disable FI & RFI interrupts */ -+ ioh_spi_disable_interrupts(pCtrlData-> -+ pMaster, -+ IOH_SPI_FI | -+ IOH_SPI_RFI); -+ -+ /*transfer is completed;inform -+ ioh_spi_process_messages */ -+ -+ if (ioh_spi_gcbptr != NULL) { -+ IOH_DEBUG -+ ("ioh_spi_handler invoking\ -+ callback\n"); -+ (*ioh_spi_gcbptr) (pCtrlData); -+ } -+ } -+ -+ tRetVal = IRQ_HANDLED; -+ } -+ } -+ } -+ -+ IOH_DEBUG("ioh_spi_handler EXIT return value=%d\n", tRetVal); -+ -+ return tRetVal; -+} -+ -+/*! @ingroup SPI_HALLayerAPI -+ -+@fn ioh_spi_entcb (void (*ioh_spi_cb)( struct ioh_spi_data* )) -+ -+@remarks Registers the callback function -+ -+ The major tasks performed by this method are: -+ - Validate ioh_spi_cb -+ - Assign it to global pointer @ref ioh_spi_gcbptr -+ -+@note This function is invoked from @ref ioh_spi_probe function -+ This function should always be invoked before the interrupt -+ handler is registered. -+ -+@param ioh_spi_cb [@ref IN] -+ Contains reference to callback function pointer -+ -+@retval None -+ -+@see -+ - ioh_spi_probe -+ -+<hr> -+ -+*/ -+void ioh_spi_entcb(void (*ioh_spi_cb) (struct ioh_spi_data *)) -+{ -+ if (ioh_spi_cb != NULL) { -+ /*Assign the above value to a global pointer */ -+ ioh_spi_gcbptr = ioh_spi_cb; -+ IOH_DEBUG("ioh_spi_entcb ioh_spi_cb ptr not NULL\n"); -+ IOH_DEBUG -+ ("ioh_spi_entcb ioh_spi_cb ptr saved in ioh_spi_gcbptr\n"); -+ } else { -+ IOH_LOG(KERN_ERR, "ioh_spi_entcb ioh_spi_cb ptr NULL\n"); -+ } -+} -+ -+/*! @ingroup SPI_HALLayerAPI -+ -+@fn ioh_spi_setup_transfer(struct spi_device *spi) -+ -+@remarks Configures the IOH SPI hardware for transfer -+ -+ The major tasks performed by this method are: -+ - Invoke @ref ioh_spi_set_baud_rate to set the baud rate. -+ - Invoke @ref ioh_spi_set_bits_per_word to set the bits per word. -+ - Set the bit justfication in SPCR. -+ - Set the Clock Polarity and Clock Phase in SPCR. -+ - Clear the Rx and Tx FIFO by toggling FICLR bit in SPCR. -+ -+@note This function configures the IOH SPI hardware according to the -+ configurations specified by the user. -+ -+@param spi [@ref IN] Contains reference to struct spi_device -+ -+@retval int -+ @ref IOH_SPI_SUCCESS All hardware configurations have been done -+ -+@see -+ - ioh_spi_select_chip -+ -+<hr> -+ -+*/ -+s8 ioh_spi_setup_transfer(struct spi_device *spi) -+{ -+ u32 reg_spcr_val; -+ -+ IOH_DEBUG("ioh_spi_setup_transfer SPBRR content =%x\n", -+ ioh_spi_readreg(spi->master, IOH_SPI_SPBRR)); -+ -+ /*set baud rate */ -+ IOH_DEBUG("ioh_spi_setup_transfer :setting baud rate=%d\n", -+ spi->max_speed_hz); -+ ioh_spi_set_baud_rate(spi->master, spi->max_speed_hz); -+ -+ /*set bits per word */ -+ IOH_DEBUG("ioh_spi_setup_transfer :setting bits_per_word=%d\n", -+ spi->bits_per_word); -+ ioh_spi_set_bits_per_word(spi->master, spi->bits_per_word); -+ -+ IOH_DEBUG -+ ("ioh_spi_setup_transfer SPBRR content after setting baud\ -+ rate & bits per word=%x\n", -+ ioh_spi_readreg(spi->master, IOH_SPI_SPBRR)); -+ -+ reg_spcr_val = ioh_spi_readreg(spi->master, IOH_SPI_SPCR); -+ IOH_DEBUG("ioh_spi_setup_transfer SPCR content = %x\n", reg_spcr_val); -+ -+ /*set bit justification */ -+ -+ if ((spi->mode & SPI_LSB_FIRST) != 0) { -+ /*LSB first */ -+ IOH_CLR_BITMSK(reg_spcr_val, SPCR_LSBF_BIT); -+ IOH_DEBUG("ioh_spi_setup_transfer :setting LSBF bit to 0\n"); -+ } else { -+ /*MSB first */ -+ IOH_SET_BITMSK(reg_spcr_val, SPCR_LSBF_BIT); -+ IOH_DEBUG("ioh_spi_setup_transfer :setting LSBF bit to 1\n"); -+ } -+ -+ /*set clock polarity */ -+ if ((spi->mode & SPI_CPOL) != 0) { -+ IOH_SET_BITMSK(reg_spcr_val, SPCR_CPOL_BIT); -+ IOH_DEBUG("ioh_spi_setup_transfer clock polarity = 1\n"); -+ } else { -+ IOH_CLR_BITMSK(reg_spcr_val, SPCR_CPOL_BIT); -+ IOH_DEBUG("ioh_spi_setup_transfer clock polarity = 0\n"); -+ } -+ -+ /*set the clock phase */ -+ if ((spi->mode & SPI_CPHA) != 0) { -+ IOH_SET_BITMSK(reg_spcr_val, SPCR_CPHA_BIT); -+ IOH_DEBUG("ioh_spi_setup_transfer clock phase = 1\n"); -+ } else { -+ IOH_CLR_BITMSK(reg_spcr_val, SPCR_CPHA_BIT); -+ IOH_DEBUG("ioh_spi_setup_transfer clock phase = 0\n"); -+ } -+ -+ /*write SPCR SPCR register */ -+ ioh_spi_writereg(spi->master, IOH_SPI_SPCR, reg_spcr_val); -+ -+ IOH_DEBUG -+ ("ioh_spi_setup_transfer SPCR content after setting LSB/MSB\ -+ and MODE= %x\n", -+ reg_spcr_val); -+ -+ /*Clear the FIFO by toggling FICLR to 1 and back to 0 */ -+ ioh_spi_clear_fifo(spi->master); -+ -+ IOH_DEBUG("ioh_spi_setup_transfer Return=%d\n", IOH_SPI_SUCCESS); -+ -+ return IOH_SPI_SUCCESS; -+} -+ -+/*! @ingroup SPI_HALLayerAPI -+ -+@fn ioh_spi_writereg(struct spi_master *master,int idx, u32 val) -+ -+@remarks Performs register writes -+ -+ The major tasks performed by this method are: -+ - Obtain the SPI channel data structure from master. -+ - Calculate the register address as offset + base address -+ from SPI channel data structure. -+ - Write the value specified by val to register the address calculated. -+ -+@note This function is inline. -+ -+@param master [@ref IN] Contains reference to struct spi_master -+ -+@param idx [@ref IN] Contains register offset -+ -+@param val [@ref IN] Contains value to be written to register -+ -+@retval None -+ -+@see -+ - ioh_spi_setup_transfer -+ - ioh_spi_enable_interrupts -+ - ioh_spi_disable_interrupts -+ - ioh_spi_set_enable -+ - ioh_spi_set_master_mode -+ - ioh_spi_set_baud_rate -+ - ioh_spi_set_bits_per_word -+ - ioh_spi_reset -+ - ioh_spi_set_threshold -+ - ioh_spi_clear_fifo -+ - ioh_spi_process_messages -+ -+<hr> -+ -+*/ -+inline void ioh_spi_writereg(struct spi_master *master, int idx, u32 val) -+{ -+ -+ struct ioh_spi_data *pCtrlData = spi_master_get_devdata(master); -+ -+ IOH_WRITE_LONG(val, (pCtrlData->IORemapAddress + idx)); -+ -+ IOH_DEBUG("ioh_spi_writereg Offset=%x\n", idx); -+ IOH_DEBUG("ioh_spi_writereg Value=%x\n", val); -+} -+ -+/*! @ingroup SPI_HALLayerAPI -+ -+@fn ioh_spi_readreg(struct spi_master *master,int idx) -+ -+@remarks Performs register reads -+ -+ The major tasks performed by this method are: -+ - Obtain the SPI channel data structure from master. -+ - Calculate the register address as offset + base address -+ from SPI channel data structure. -+ - Read the content of the register at the address calculated. -+ -+@note This function is inline -+ -+@param master [@ref IN] Contains reference to struct spi_master -+ -+@param idx [@ref IN] Contains register offset -+ -+@retval u32 -+ The content of the register at offset idx -+ -+@see -+ - ioh_spi_setup_transfer -+ - ioh_spi_enable_interrupts -+ - ioh_spi_disable_interrupts -+ - ioh_spi_set_enable -+ - ioh_spi_set_master_mode -+ - ioh_spi_set_baud_rate -+ - ioh_spi_set_bits_per_word -+ - ioh_spi_set_threshold -+ - ioh_spi_clear_fifo -+ -+<hr> -+*/ -+inline u32 ioh_spi_readreg(struct spi_master *master, int idx) -+{ -+ u32 reg_data; -+ -+ struct ioh_spi_data *pCtrlData = spi_master_get_devdata(master); -+ -+ IOH_DEBUG("ioh_spi_readreg Offset=%x\n", idx); -+ reg_data = IOH_READ_LONG((pCtrlData->IORemapAddress + idx)); -+ -+ IOH_DEBUG("ioh_spi_readreg Content=%x\n", reg_data); -+ return reg_data; -+} -+ -+/*! @ingroup SPI_HALLayerAPI -+ -+@fn ioh_spi_enable_interrupts (struct spi_master *master, u8 interrupt) -+ -+@remarks Enables specified interrupts -+ -+ The major tasks performed by this method are: -+ - Read the content of SPCR. -+ - Based on interrupt ,set corresponding bits in SPCR content. -+ - Write the value back to SPCR. -+ -+@note This function is invoked from @ref ioh_spi_process_messages before -+ starting SPI data transfer.As of now only FI and RFI interrupts are -+ used. -+ -+@param master [@ref IN] Contains reference to struct spi_master -+ -+@param interrupt [@ref IN] Interrups to be enabled.This parameter -+ is a u8 value with five least significant bits representing -+ each of the interrupts FI,RFI,TFI,ORI and MDFI. -+ -+@retval None -+ -+@see -+ - ioh_spi_process_messages -+ -+<hr> -+ -+*/ -+void ioh_spi_enable_interrupts(struct spi_master *master, u8 interrupt) -+{ -+ u32 reg_val_spcr; -+ -+ reg_val_spcr = ioh_spi_readreg(master, IOH_SPI_SPCR); -+ -+ IOH_DEBUG("ioh_spi_enable_interrupts SPCR content=%x\n", reg_val_spcr); -+ -+ if ((interrupt & IOH_SPI_RFI) != 0) { -+ /*set RFIE bit in SPCR */ -+ IOH_DEBUG("setting RFI in ioh_spi_enable_interrupts\n"); -+ IOH_SET_BITMSK(reg_val_spcr, SPCR_RFIE_BIT); -+ } -+ -+ if ((interrupt & IOH_SPI_TFI) != 0) { -+ /*set TFIE bit in SPCR */ -+ IOH_DEBUG("setting TFI in ioh_spi_enable_interrupts\n"); -+ IOH_SET_BITMSK(reg_val_spcr, SPCR_TFIE_BIT); -+ } -+ -+ if ((interrupt & IOH_SPI_FI) != 0) { -+ /*set FIE bit in SPCR */ -+ IOH_DEBUG("setting FI in ioh_spi_enable_interrupts\n"); -+ IOH_SET_BITMSK(reg_val_spcr, SPCR_FIE_BIT); -+ } -+ -+ if ((interrupt & IOH_SPI_ORI) != 0) { -+ /*set ORIE bit in SPCR */ -+ IOH_DEBUG("setting ORI in ioh_spi_enable_interrupts\n"); -+ IOH_SET_BITMSK(reg_val_spcr, SPCR_ORIE_BIT); -+ } -+ -+ if ((interrupt & IOH_SPI_MDFI) != 0) { -+ /*set MODFIE bit in SPCR */ -+ IOH_DEBUG("setting MDFI in ioh_spi_enable_interrupts\n"); -+ IOH_SET_BITMSK(reg_val_spcr, SPCR_MDFIE_BIT); -+ } -+ -+ ioh_spi_writereg(master, IOH_SPI_SPCR, reg_val_spcr); -+ -+ IOH_DEBUG -+ ("ioh_spi_enable_interrupts SPCR content after enabling interrupt\ -+ =%x\n", -+ reg_val_spcr); -+} -+ -+/*! @ingroup SPI_HALLayerAPI -+ -+@fn ioh_spi_disable_interrupts (struct spi_master *master, u8 interrupt) -+ -+@remarks Disables specified interrupts -+ -+ The major tasks performed by this method are: -+ - Read the content of SPCR. -+ - Based on interrupt ,clear corresponding bits in SPCR content. -+ - Write the value back to SPCR. -+ -+@param master [@ref IN] Contains reference to struct spi_master -+ -+@param interrupt [@ref IN] Interrups to be disabled.This parameter -+ is a u8 value with five least significant bits representing -+ each of the interrupts FI,RFI,TFI,ORI and MDFI. -+ -+@retval None -+ -+@see -+ - ioh_spi_process_messages -+ - ioh_spi_handler -+ - ioh_spi_suspend -+ - ioh_spi_free_resources -+ -+<hr> -+ -+*/ -+void ioh_spi_disable_interrupts(struct spi_master *master, u8 interrupt) -+{ -+ u32 reg_val_spcr; -+ -+ reg_val_spcr = ioh_spi_readreg(master, IOH_SPI_SPCR); -+ -+ IOH_DEBUG("ioh_spi_disable_interrupts SPCR content =%x\n", -+ reg_val_spcr); -+ -+ if ((interrupt & IOH_SPI_RFI) != 0) { -+ /*clear RFIE bit in SPCR */ -+ IOH_DEBUG("clearing RFI in ioh_spi_disable_interrupts\n"); -+ IOH_CLR_BITMSK(reg_val_spcr, SPCR_RFIE_BIT); -+ } -+ -+ if ((interrupt & IOH_SPI_TFI) != 0) { -+ /*clear TFIE bit in SPCR */ -+ IOH_DEBUG("clearing TFI in ioh_spi_disable_interrupts\n"); -+ IOH_CLR_BITMSK(reg_val_spcr, SPCR_TFIE_BIT); -+ } -+ -+ if ((interrupt & IOH_SPI_FI) != 0) { -+ /*clear FIE bit in SPCR */ -+ IOH_DEBUG("clearing FI in ioh_spi_disable_interrupts\n"); -+ IOH_CLR_BITMSK(reg_val_spcr, SPCR_FIE_BIT); -+ } -+ -+ if ((interrupt & IOH_SPI_ORI) != 0) { -+ /*clear ORIE bit in SPCR */ -+ IOH_DEBUG("clearing ORI in ioh_spi_disable_interrupts\n"); -+ IOH_CLR_BITMSK(reg_val_spcr, SPCR_ORIE_BIT); -+ } -+ -+ if ((interrupt & IOH_SPI_MDFI) != 0) { -+ /*clear MODFIE bit in SPCR */ -+ IOH_DEBUG("clearing MDFI in ioh_spi_disable_interrupts\n"); -+ IOH_CLR_BITMSK(reg_val_spcr, SPCR_MDFIE_BIT); -+ } -+ -+ ioh_spi_writereg(master, IOH_SPI_SPCR, reg_val_spcr); -+ -+ IOH_DEBUG -+ ("ioh_spi_disable_interrupts SPCR after disabling interrupts =%x\n", -+ reg_val_spcr); -+} -+ -+/*! @ingroup SPI_HALLayerAPI -+ -+@fn ioh_spi_set_threshold(struct spi_device *spi, u32 threshold, u8 dir) -+ -+@remarks Sets Tx/Rx FIFO thresholds -+ -+The major tasks performed by this function are: -+- Read the content of SPCR. -+- If the dir is @ref IOH_SPI_RX ,set the Rx threshold bits in SPCR content. -+- If the dir is @ref IOH_SPI_TX ,set the Tx threshold bits in SPCR content. -+- Write back the value to SPCR. -+ -+@note This function is invoked from ioh_spi_process_messages to set the Receive -+threshold level.As of now, when the length of data to be transferred is greater -+than FIFO depth of 16 bytes/words ,the Receive FIFO threshold is set at -+ 8 bytes/words. -+If the length of data to be transferred is less than FIFO depth,the Receive FIFO -+threshold is set at 16 bytes/words. -+ -+@param spi [@ref IN] Contains reference to struct spi_device -+ -+@param threshold [@ref IN] Threshold value to be set -+ -+@param dir [@ref IN] Rx or Tx threshold to be set -+ - dir = @ref IOH_SPI_RX implies Receive FIFO threshold needs to be set. -+ - dir = @ref IOH_SPI_TX implies Transmit FIFO threshold needs to be set. -+ -+@retval None -+ -+@see -+ - ioh_spi_process_messages -+ -+<hr> -+*/ -+void ioh_spi_set_threshold(struct spi_device *spi, u32 threshold, u8 dir) -+{ -+ u32 reg_val_spcr; -+ -+ reg_val_spcr = ioh_spi_readreg(spi->master, IOH_SPI_SPCR); -+ IOH_DEBUG("ioh_spi_set_threshold SPCR before modifying =%x\n", -+ reg_val_spcr); -+ IOH_DEBUG("ioh_spi_set_threshold threshold=%d\n", (threshold + 1)); -+ -+ if (dir == IOH_SPI_RX) { -+ IOH_DEBUG("ioh_spi_set_threshold setting Rx threshold\n"); -+ reg_val_spcr &= MASK_RFIC_SPCR_BITS; -+ reg_val_spcr |= (threshold << SPCR_RFIC_FIELD); -+ } else if (dir == IOH_SPI_TX) { -+ IOH_DEBUG("ioh_spi_set_threshold setting Tx threshold\n"); -+ reg_val_spcr &= MASK_TFIC_SPCR_BITS; -+ reg_val_spcr |= (threshold << SPCR_TFIC_FIELD); -+ } -+ -+ ioh_spi_writereg(spi->master, IOH_SPI_SPCR, reg_val_spcr); -+ -+ IOH_DEBUG("ioh_spi_set_threshold SPCR after modifying =%x\n", -+ reg_val_spcr); -+} -+ -+/*! @ingroup SPI_HALLayerAPI -+ -+@fn ioh_spi_reset(struct spi_master* master) -+ -+@remarks Clears SPI registers -+ -+ The major tasks performed by this method are: -+ - Clear all R/W bits of SPCR. -+ - Clear Receive and Transmit FIFOs by invoking @ref ioh_spi_clear_fifo -+ - Clear all R/W bits of SPBRR. -+ - Clear all interrupts in SPSR. -+ - If the device has SRST [reset register],then instead of the -+ above steps,first 1 is written to SRST to reset SPI and then -+ 0 is written to SRST to clear reset. -+ -+@note This function is invoked to bring the IOH SPI device to an -+ initialized state.After this function is invoked all the SPI -+ registers need to be configured again. -+ -+@param master [@ref IN] Contains reference to struct spi_master -+ -+@retval None -+ -+@see -+ - ioh_spi_get_resources -+ - ioh_spi_suspend -+ - ioh_spi_resume -+ -+<hr> -+ -+*/ -+void ioh_spi_reset(struct spi_master *master) -+{ -+#ifndef FPGA -+ /*LSI*/ -+ /*write 1 to reset SPI */ -+ ioh_spi_writereg(master, IOH_SPI_SRST, 0x1); -+ /*clear reset */ -+ ioh_spi_writereg(master, IOH_SPI_SRST, 0x0); -+#else -+ /*FPGA*/ -+ /*write 0 to SPCR */ -+ ioh_spi_writereg(master, IOH_SPI_SPCR, 0x0); -+ IOH_DEBUG("ioh_spi_reset SPCR content after reset=%x\n", -+ ioh_spi_readreg(master, IOH_SPI_SPCR)); -+ /*Clear the FIFO */ -+ ioh_spi_clear_fifo(master); -+ -+ /*write 0 to SPBRR */ -+ ioh_spi_writereg(master, IOH_SPI_SPBRR, 0x0); -+ IOH_DEBUG("ioh_spi_reset SPBRR content after reset=%x\n", -+ ioh_spi_readreg(master, IOH_SPI_SPBRR)); -+ -+ /*clear interrupts in SPSR */ -+ ioh_spi_writereg(master, IOH_SPI_SPSR, SPSR_INT_BITS); -+ IOH_DEBUG("ioh_spi_reset SPSR content after reset=%x\n", -+ ioh_spi_readreg(master, IOH_SPI_SPSR)); -+#endif -+} -+ -+/*! @ingroup SPI_HALLayerAPI -+ -+@fn ioh_spi_set_baud_rate(struct spi_master* master,u32 speed_hz) -+ -+@remarks Sets SPBR field in SPBRR -+ -+ The major tasks performed by this method are: -+ - Read the content of SPBRR register. -+ - Calculate the value for SPBR field according to the baud rate. -+ - Set the SPBR field using the calculated value. -+ - Write the conetnt back to SPBRR. -+ -+@note The SPBR value is calculated from the baud rate using the formula -+ SPBR = clock frequency / baud rate. -+ -+@param master [@ref IN] Contains reference to struct spi_master -+ -+@param speed_hz [@ref IN] Baud rate to be set -+ -+@retval None -+ -+@see -+ - ioh_spi_setup_transfer -+ - ioh_spi_process_messages -+ -+<hr> -+ -+*/ -+void ioh_spi_set_baud_rate(struct spi_master *master, u32 speed_hz) -+{ -+ u32 nSpbr, reg_spbrr_val; -+ -+ nSpbr = IOH_CLOCK_HZ / (speed_hz * 2); -+ -+ /*if baud rate is less than we can support -+ limit it */ -+ -+ if (nSpbr > IOH_SPI_MAX_SPBR) -+ nSpbr = IOH_SPI_MAX_SPBR; -+ -+ -+ reg_spbrr_val = ioh_spi_readreg(master, IOH_SPI_SPBRR); -+ -+ IOH_DEBUG("ioh_spi_set_baud_rate SPBRR content=%x\n", reg_spbrr_val); -+ -+ IOH_DEBUG("ioh_spi_set_baud_rate SPBR in SPBRR=%d\n", nSpbr); -+ -+ /*clear SPBRR */ -+ reg_spbrr_val &= MASK_SPBRR_SPBR_BITS; -+ -+ /*set the new value */ -+ reg_spbrr_val |= nSpbr; -+ -+ /*write the new value */ -+ ioh_spi_writereg(master, IOH_SPI_SPBRR, reg_spbrr_val); -+ IOH_DEBUG("ioh_spi_set_baud_rate SPBRR content after setting SPBR=%x\n", -+ reg_spbrr_val); -+} -+ -+/*! @ingroup SPI_HALLayerAPI -+ -+@fn ioh_spi_set_bits_per_word(struct spi_master* master,u8 bits_per_word) -+ -+@remarks Sets SIZE field in SPBRR -+ -+ The major tasks performed by this method are: -+ - Read the content of SPBRR register. -+ - Set the SIZE field in SPBRR according to bits per word. -+ - Write back the value to SPBRR. -+ -+@note The allowed bits per word settings are 8 and 16.The SIZE bit in SPBRR is -+ 0 denotes bits per word of 8 and SIZE bit 1 denotes bits per word of 16. -+ -+@param master [@ref IN] Contains reference to struct spi_master -+ -+@param bits_per_word [@ref IN] Bits per word for SPI transfer -+ -+@retval None -+ -+@see -+ - ioh_spi_setup_transfer -+ - ioh_spi_process_messages -+ -+<hr> -+ -+*/ -+void ioh_spi_set_bits_per_word(struct spi_master *master, u8 bits_per_word) -+{ -+ u32 reg_spbrr_val = ioh_spi_readreg(master, IOH_SPI_SPBRR); -+ IOH_DEBUG("ioh_spi_set_bits_per_word SPBRR content=%x\n", -+ reg_spbrr_val); -+ -+ if (bits_per_word == IOH_SPI_8_BPW) { -+ IOH_CLR_BITMSK(reg_spbrr_val, SPBRR_SIZE_BIT); -+ IOH_DEBUG("ioh_spi_set_bits_per_word 8\n"); -+ } else { -+ IOH_SET_BITMSK(reg_spbrr_val, SPBRR_SIZE_BIT); -+ IOH_DEBUG("ioh_spi_set_bits_per_word 16\n"); -+ } -+ -+ ioh_spi_writereg(master, IOH_SPI_SPBRR, reg_spbrr_val); -+ -+ IOH_DEBUG -+ ("ioh_spi_set_bits_per_word SPBRR after setting bits per word=%x\n", -+ reg_spbrr_val); -+} -+ -+/*! @ingroup SPI_HALLayerAPI -+ -+@fn ioh_spi_clear_fifo(struct spi_master *master) -+ -+@remarks Clears the Transmit and Receive FIFOs -+ -+ The major tasks performed by this method are: -+ - Read the content of SPCR. -+ - Set FICLR bit to 1. -+ - Write back the content to SPCR. -+ - Set the FICLR bit to 0. -+ - Write back the content to SPCR. -+ -+@param master [@ref IN] Contains reference to struct spi_master -+ -+@retval None -+ -+@see -+ - ioh_spi_setup_transfer -+ - ioh_spi_process_messages -+ -+<hr> -+ -+*/ -+void ioh_spi_clear_fifo(struct spi_master *master) -+{ -+ u32 reg_spcr_val = ioh_spi_readreg(master, IOH_SPI_SPCR); -+ -+ IOH_SET_BITMSK(reg_spcr_val, SPCR_FICLR_BIT); -+ ioh_spi_writereg(master, IOH_SPI_SPCR, reg_spcr_val); -+ IOH_DEBUG("ioh_spi_clear_fifo SPCR content after setting FICLR = %x\n", -+ reg_spcr_val); -+ -+ IOH_CLR_BITMSK(reg_spcr_val, SPCR_FICLR_BIT); -+ ioh_spi_writereg(master, IOH_SPI_SPCR, reg_spcr_val); -+ -+ IOH_DEBUG -+ ("ioh_spi_clear_fifo SPCR content after resetting FICLR = %x\n", -+ reg_spcr_val); -+} -diff -urN linux-2.6.33-rc3/drivers/spi/pch_spi_hal.h topcliff-2.6.33-rc3/drivers/spi/pch_spi_hal.h ---- linux-2.6.33-rc3/drivers/spi/pch_spi_hal.h 1970-01-01 09:00:00.000000000 +0900 -+++ topcliff-2.6.33-rc3/drivers/spi/pch_spi_hal.h 2010-03-06 09:02:20.000000000 +0900 -@@ -0,0 +1,298 @@ -+/** -+ * @file ioh_spi_hal.h -+ * -+ * @brief This header file contains macro definitions and function declarations -+ * for HAL layer APIs. -+ * @version 0.94 -+ * -+ * @par -+ * -- Copyright Notice -- -+ * -+ * @par -+ * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD. -+ * All rights reserved. -+ * -+ * @par -+ * 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. -+ * -+ * @par -+ * -- End of Copyright Notice -- -+ */ -+#ifndef __IOH_SPI_HAL__ -+#define __IOH_SPI_HAL__ -+ -+/*Register offsets*/ -+ -+/*! @ingroup SPI_HALLayer -+@def IOH_SPI_SPCR -+@brief SPCR register offset -+*/ -+#define IOH_SPI_SPCR (0x00) /*SPI control register */ -+ -+/*! @ingroup SPI_HALLayer -+@def IOH_SPI_SPBRR -+@brief SPBRR register offset -+*/ -+#define IOH_SPI_SPBRR (0x04) /*SPI baud rate register */ -+ -+/*! @ingroup SPI_HALLayer -+@def IOH_SPI_SPSR -+@brief SPSR register offset -+*/ -+#define IOH_SPI_SPSR (0x08) /*SPI status register */ -+ -+/*! @ingroup SPI_HALLayer -+@def IOH_SPI_SPDWR -+@brief SPDWR register offset -+*/ -+#define IOH_SPI_SPDWR (0x0C) /*SPI write data register */ -+ -+/*! @ingroup SPI_HALLayer -+@def IOH_SPI_SPDRR -+@brief SPDRR register offset -+*/ -+#define IOH_SPI_SPDRR (0x10) /*SPI read data register */ -+ -+/*! @ingroup SPI_HALLayer -+@def IOH_SPI_SSNXCR -+@brief SSNXCR register offset -+*/ -+#define IOH_SPI_SSNXCR (0x18)/* SSN Expand Control Register */ -+ -+/*! @ingroup SPI_HALLayer -+@def IOH_SPI_SRST -+@brief SRST register offset -+*/ -+#define IOH_SPI_SRST (0x1C) /*SPI reset register */ -+ -+/* valid bits per word settings*/ -+ -+/*! @ingroup SPI_HALLayer -+@def IOH_SPI_8_BPW -+@brief Macro to denote 8 Bits per word transfer -+*/ -+#define IOH_SPI_8_BPW (8) -+ -+/*! @ingroup SPI_HALLayer -+@def IOH_SPI_16_BPW -+@brief Macro to denote 16 Bits per word transfer -+*/ -+#define IOH_SPI_16_BPW (16) -+ -+/*! @ingroup SPI_HALLayer -+@def IOH_SPI_SPSR_TFD -+@brief Mask to obtaining TFD bits from SPSR -+*/ -+#define IOH_SPI_SPSR_TFD (0x000007C0) -+ -+/*! @ingroup SPI_HALLayer -+@def IOH_SPI_SPSR_RFD -+@brief Mask to obtaining RFD bits from SPSR -+*/ -+#define IOH_SPI_SPSR_RFD (0x0000F800) -+ -+/*! @ingroup SPI_HALLayer -+@def IOH_SPI_READABLE(x) -+@brief Macro to obtain number of bytes received in Rx FIFO -+@note x is the content of SPSR register -+*/ -+#define IOH_SPI_READABLE(x) (((x) & IOH_SPI_SPSR_RFD)>>11) -+ -+/*! @ingroup SPI_HALLayer -+@def IOH_SPI_WRITABLE(x) -+@brief Macro to obtain number of bytes te be transmitted in Tx FIFO -+@note x is the content of SPSR register -+*/ -+#define IOH_SPI_WRITABLE(x) (((x) & IOH_SPI_SPSR_TFD)>>6) -+ -+/*! @ingroup SPI_HALLayer -+@def IOH_SPI_RX_THOLD -+@brief Macro to denote Rx interrupt threshold -+@note Currently set to interrupt when 8 bytes are received -+*/ -+/*set to interrupt when 8 bytes have been received */ -+#define IOH_SPI_RX_THOLD (7) -+ -+/*! @ingroup SPI_HALLayer -+@def IOH_SPI_RX_THOLD_MAX -+@brief Macro to denote Rx interrupt threshold when Rx FIFO is full -+*/ -+/*set to interrupt when 16 bytes have been received */ -+#define IOH_SPI_RX_THOLD_MAX (15) -+ -+/*direction for interrupts*/ -+ -+/*! @ingroup SPI_HALLayer -+@def IOH_SPI_RX -+@brief Macro to indicate Receive -+*/ -+#define IOH_SPI_RX (1) -+ -+/*! @ingroup SPI_HALLayer -+@def IOH_SPI_TX -+@brief Macro to indicate Transmit -+*/ -+#define IOH_SPI_TX (2) -+ -+/*various interrupts*/ -+ -+/*! @ingroup SPI_HALLayer -+@def IOH_SPI_TFI -+@brief Transmit interrupt -+*/ -+#define IOH_SPI_TFI (0x1) -+ -+/*! @ingroup SPI_HALLayer -+@def IOH_SPI_RFI -+@brief Receive interrupt -+*/ -+#define IOH_SPI_RFI (0x2) -+ -+/*! @ingroup SPI_HALLayer -+@def IOH_SPI_FI -+@brief Transfer complete interrupt -+*/ -+#define IOH_SPI_FI (0x4) -+ -+/*! @ingroup SPI_HALLayer -+@def IOH_SPI_ORI -+@brief Overflow interrupt -+*/ -+#define IOH_SPI_ORI (0x8) -+ -+/*! @ingroup SPI_HALLayer -+@def IOH_SPI_MDFI -+@brief Modefault interrupt -+*/ -+#define IOH_SPI_MDFI (0x10) -+ -+/*! @ingroup SPI_HALLayer -+@def IOH_SPI_ALL -+@brief Macro to denote all interrupts -+*/ -+#define IOH_SPI_ALL \ -+ (IOH_SPI_TFI|IOH_SPI_RFI|IOH_SPI_FI|IOH_SPI_ORI|IOH_SPI_MDFI) -+ -+/*! @ingroup SPI_HALLayer -+@def IOH_SPI_MAX_BAUDRATE -+@brief Macro to denote maximum possible baud rate in bits per second -+*/ -+#define IOH_SPI_MAX_BAUDRATE (5000000) -+ -+/*! @ingroup SPI_HALLayer -+@def IOH_SPI_MAX_FIFO_DEPTH -+@brief Macro to denote maximum FIFO depth(16) -+*/ -+#define IOH_SPI_MAX_FIFO_DEPTH (16) -+ -+/*status codes*/ -+ -+/*! @ingroup SPI_Global -+@def IOH_SPI_SUCCESS -+@brief Success status code -+*/ -+#define IOH_SPI_SUCCESS (0) -+ -+/*! @ingroup SPI_Global -+@def IOH_SPI_FAIL -+@brief Failure status code -+*/ -+#define IOH_SPI_FAIL (-1) -+ -+/* hal function prototypes */ -+ -+/*! @ingroup SPI_HALLayerAPI -+@fn ioh_spi_setup_transfer(struct spi_device *spi) -+@brief Configures the IOH SPI hardware for SPI transfer -+*/ -+s8 ioh_spi_setup_transfer(struct spi_device *spi); -+ -+/*! @ingroup SPI_HALLayerAPI -+@fn ioh_spi_set_enable(const struct spi_device *spi, u8 enable) -+@brief Sets/Resets SPE bit in SPCR based on enable parameter -+*/ -+void ioh_spi_set_enable(const struct spi_device *spi, u8 enable); -+ -+/*! @ingroup SPI_HALLayerAPI -+@fn ioh_spi_set_master_mode( struct spi_master *master) -+@brief Sets MSTR bit in SPCR -+*/ -+void ioh_spi_set_master_mode(struct spi_master *master); -+ -+/*! @ingroup SPI_HALLayerAPI -+@fn ioh_spi_writereg(struct spi_master *master,int idx, u32 val) -+@brief Performs register writes -+*/ -+inline void ioh_spi_writereg(struct spi_master *master, int idx, u32 val); -+ -+/*! @ingroup SPI_HALLayerAPI -+@fn ioh_spi_readreg(struct spi_master *master,int idx) -+@brief Performs register reads -+*/ -+inline u32 ioh_spi_readreg(struct spi_master *master, int idx); -+ -+/*! @ingroup SPI_HALLayerAPI -+@fn ioh_spi_handler (int irq, void* dev_id) -+@brief The interrupt handler -+*/ -+irqreturn_t ioh_spi_handler(int irq, void *dev_id); -+ -+/*! @ingroup SPI_HALLayerAPI -+@fn ioh_spi_entcb (void (*ioh_spi_cb)( struct ioh_spi_data* )) -+@brief Registers the Callback function -+*/ -+void ioh_spi_entcb(void (*ioh_spi_cb) (struct ioh_spi_data *)); -+ -+/*! @ingroup SPI_HALLayerAPI -+@fn ioh_spi_enable_interrupts (struct spi_master *master ,u8 interrupt) -+@brief Enables specified interrupts in SPCR -+*/ -+void ioh_spi_enable_interrupts(struct spi_master *master, u8 interrupt); -+ -+/*! @ingroup SPI_HALLayerAPI -+@fn ioh_spi_disable_interrupts (struct spi_master *master ,u8 interrupt) -+@brief Disables specified interrupts in SPCR -+*/ -+void ioh_spi_disable_interrupts(struct spi_master *master, u8 interrupt); -+ -+/*! @ingroup SPI_HALLayerAPI -+@fn ioh_spi_set_threshold(struct spi_device *spi,u32 threshold, u8 dir) -+@brief Sets RFIC/TFIC fields in SPCR based on threshold and dir -+*/ -+void ioh_spi_set_threshold(struct spi_device *spi, u32 threshold, u8 dir); -+ -+/*! @ingroup SPI_HALLayerAPI -+@fn ioh_spi_reset(struct spi_master *master) -+@brief Resets IOH SPI register settings -+*/ -+void ioh_spi_reset(struct spi_master *master); -+ -+/*! @ingroup SPI_HALLayerAPI -+@fn ioh_spi_set_baud_rate(struct spi_master *master,u32 speed_hz) -+@brief Sets SPBR field in SPBRR -+*/ -+void ioh_spi_set_baud_rate(struct spi_master *master, u32 speed_hz); -+ -+/*! @ingroup SPI_HALLayerAPI -+@fn ioh_spi_set_bits_per_word(struct spi_master *master,u8 bits_per_word) -+@brief Sets SIZE field in SPBRR -+*/ -+void ioh_spi_set_bits_per_word(struct spi_master *master, u8 bits_per_word); -+ -+/*! @ingroup SPI_HALLayerAPI -+@fn ioh_spi_clear_fifo(struct spi_master *master) -+@brief Clears Tx/Rx FIFOs by toggling FICLR bit in SPCR -+*/ -+void ioh_spi_clear_fifo(struct spi_master *master); -+#endif -diff -urN linux-2.6.33-rc3/drivers/spi/pch_spi_main.c topcliff-2.6.33-rc3/drivers/spi/pch_spi_main.c ---- linux-2.6.33-rc3/drivers/spi/pch_spi_main.c 1970-01-01 09:00:00.000000000 +0900 -+++ topcliff-2.6.33-rc3/drivers/spi/pch_spi_main.c 2010-03-09 00:40:52.000000000 +0900 -@@ -0,0 +1,1323 @@ -+/** -+ * @file ioh_spi_main.c -+ * -+ * @brief This file defines the SPI_InterfaceLayer APIs of the IOH SPI -+ * controller -+ * driver. -+ * -+ * @version 0.94 -+ * -+ * @par -+ * -- Copyright Notice -- -+ * -+ * @par -+ * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD. -+ * All rights reserved. -+ * -+ * @par -+ * 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. -+ * -+ * @par -+ * -- End of Copyright Notice -- -+ */ -+ -+#include <linux/pci.h> -+#include <linux/wait.h> -+#include <linux/spi/spi.h> -+#include <linux/interrupt.h> -+#include <linux/sched.h> -+#include "pch_debug.h" -+#include "pch_spi.h" -+#include "pch_spi_hal.h" -+ -+/*! @ingroup SPI_HALLayer -+@def SSN_LOW -+@brief SSNXCR register value to pull down SSN -+*/ -+#define SSN_LOW (0x02U) -+ -+/*! @ingroup SPI_HALLayer -+@def SSN_NO_CONTROL -+@brief SSNXCR register value to relinquish control over SSN -+*/ -+#define SSN_NO_CONTROL (0x00U) -+ -+/*function prototypes*/ -+ -+/*! @ingroup SPI_UtilitiesAPI -+@fn ioh_spi_deselect_chip(struct ioh_spi_data* pCtrlData) -+@brief Clears the details of the current slave from the SPI channel -+ data structure -+*/ -+static inline void ioh_spi_deselect_chip(struct ioh_spi_data *pCtrlData); -+ -+/*! @ingroup SPI_UtilitiesAPI -+@fn ioh_spi_select_chip(struct ioh_spi_data* pCtrlData,struct spi_device* pSpi) -+@brief Update the slave device details in the SPI channel data structure -+*/ -+static inline void ioh_spi_select_chip(struct ioh_spi_data *pCtrlData, -+ struct spi_device *pSpi); -+ -+/*! @ingroup SPI_UtilitiesAPI -+@fn ioh_spi_process_messages(struct work_struct* pWork) -+@brief Work Queue handler to handle SPI data transfers -+*/ -+static void ioh_spi_process_messages(struct work_struct *pWork); -+ -+/*! @ingroup SPI_UtilitiesAPI -+ -+@fn ioh_spi_get_resources(struct ioh_spi_board_data* pBoardData) -+ -+@remarks Acquires the resources needed by IOH SPI driver -+ -+ The major tasks performed by this method are: -+ - Initialize the spin lock of all SPI channels. -+ - Initialize queue to hold pending SPI messages of all SPI channels. -+ - Initialize wait queue head of all SPI channels. -+ - Create the work structure for all SPI channels. -+ - Create the work queues for all SPI channels. -+ - Allocate PCI regions. -+ - Get PCI memory mapped address and base addresses for all SPI channels. -+ - Reset the IOH SPI hardware for all SPI channels. -+ - Register the interrupt handler. -+ -+@note This function is invoked by ioh_spi_probe to acquire -+ the various resources needed by IOH SPI driver.If any of the actions -+ performed by ioh_spi_get_resources fails,@ref ioh_spi_free_resources -+ is invoked to perform the necessary cleanups. -+ -+@param pBoardData [@ref INOUT] -+ Contains the reference to struct ioh_spi_board_data -+ -+@retval int -+- @ref IOH_SPI_SUCCESS The function terminates normally after all -+ required resources are acquired. -+- -EBUSY create_singlethread_workqueue fails. -+ pci_request_regions fails. -+ request_irq fails. -+- -EINVAL request_irq fails. -+- -ENOSYS request_irq_fails. -+- -ENOMEM pci_iomap_fails. -+ request_irq fails. -+ -+@see -+ - ioh_spi_probe -+ -+<hr> -+*/ -+int ioh_spi_get_resources(struct ioh_spi_board_data *pBoardData) -+{ -+ int i; -+ long IORemapAddress; -+ s32 iRetVal = IOH_SPI_SUCCESS; -+ IOH_DEBUG("ioh_spi_get_resources ENTRY\n"); -+ -+ /*initialize resources */ -+ -+ for (i = 0; i < IOH_SPI_MAX_DEV; i++) { -+ /*iniatize queue of pending messages */ -+ INIT_LIST_HEAD(&(pBoardData->pCtrlData[i]->Queue)); -+ IOH_DEBUG -+ ("ioh_spi_get_resources pCtrlData[i]->Queue initialized using" -+ "INIT_LIST_HEAD\n"); -+ -+ /*initialize spin locks */ -+ spin_lock_init(&(pBoardData->pCtrlData[i]->Lock)); -+ IOH_DEBUG -+ ("ioh_spi_get_resources pCtrlData[i]->Lock initialized using" -+ "spin_lock_init\n"); -+ -+ /*set channel status */ -+ pBoardData->pCtrlData[i]->Status = STATUS_RUNNING; -+ IOH_DEBUG -+ ("ioh_spi_get_resources pCtrlData[i]->Status\ -+ = STATUS_RUNNING\n"); -+ -+ /*initialize work structure */ -+ INIT_WORK(&(pBoardData->pCtrlData[i]->Work), -+ ioh_spi_process_messages); -+ IOH_DEBUG -+ ("ioh_spi_get_resources pCtrlData[i]->Work initialized\ -+ using INIT_WORK\n"); -+ -+ /*initialize wait queues */ -+ init_waitqueue_head(&(pBoardData->pCtrlData[i]->Wait)); -+ IOH_DEBUG -+ ("ioh_spi_get_resources pCtrlData[i]->Wait initialized\ -+ using init_waitqueue_head\n"); -+ } -+ -+ do { -+ for (i = 0; i < IOH_SPI_MAX_DEV; i++) { -+ /*create workqueue */ -+ pBoardData->pCtrlData[i]->pWorkQueue = -+ create_singlethread_workqueue(DRIVER_NAME); -+ -+ if ((pBoardData->pCtrlData[i]->pWorkQueue) == NULL) { -+ IOH_LOG(KERN_ERR, -+ "ioh_spi_get_resources create_singlet\ -+ hread_workqueue failed\n"); -+ iRetVal = -EBUSY; -+ break; -+ } -+ } -+ -+ if (iRetVal != 0) -+ break; -+ -+ -+ IOH_DEBUG -+ ("ioh_spi_get_resources create_singlethread_workqueue\ -+ success\n"); -+ iRetVal = pci_request_regions(pBoardData->pDev, DRIVER_NAME); -+ if (iRetVal != 0) { -+ IOH_LOG(KERN_ERR, -+ "ioh_spi_get_resources request_region failed\n"); -+ break; -+ } -+ -+ IOH_DEBUG("ioh_spi_get_resources request_region returned=%d\n", -+ iRetVal); -+ -+ pBoardData->bRegionRequested = true; -+ IOH_DEBUG -+ ("ioh_spi_get_resources pCtrlData->bRegionRequested = true\n"); -+ -+ /* Wipro 1/13/2010 Use Mem BAR */ -+ IORemapAddress = -+ (unsigned long)pci_iomap(pBoardData->pDev, 1, 0); -+ -+ if (IORemapAddress == 0) { -+ IOH_LOG(KERN_ERR, -+ "ioh_spi_get_resources pci_iomap failed\n"); -+ iRetVal = -ENOMEM; -+ break; -+ } -+ -+ IOH_DEBUG -+ ("ioh_spi_get_resources pci_iomap success PCI Base\ -+ address=%x\n", -+ (IORemapAddress)); -+ -+ /*calculate base address for all channels */ -+ -+ for (i = 0; i < IOH_SPI_MAX_DEV; i++) { -+ pBoardData->pCtrlData[i]->IORemapAddress = -+ IORemapAddress + (IOH_SPI_ADDRESS_SIZE * i); -+ IOH_DEBUG -+ ("ioh_spi_get_resources Base address for\ -+ channel %d= %x\n", -+ i, (pBoardData->pCtrlData[i]->IORemapAddress)); -+ } -+ -+ /*reset IOH SPI h/w */ -+ for (i = 0; i < IOH_SPI_MAX_DEV; i++) { -+ ioh_spi_reset(pBoardData->pCtrlData[i]->pMaster); -+ IOH_DEBUG -+ ("ioh_spi_get_resources ioh_spi_reset invoked\ -+ successfully \n"); -+ } -+ -+ /*register IRQ */ -+ iRetVal = request_irq(pBoardData->pDev->irq, ioh_spi_handler, -+ IRQF_SHARED, DRIVER_NAME, -+ (void *)pBoardData); -+ if (iRetVal != 0) { -+ IOH_LOG(KERN_ERR, -+ "ioh_spi_get_resources request_irq failed\n"); -+ break; -+ } -+ -+ IOH_DEBUG("ioh_spi_get_resources request_irq returned=%d\n", -+ iRetVal); -+ -+ pBoardData->bIrqRegistered = true; -+ IOH_DEBUG -+ ("ioh_spi_get_resources pCtrlData->bIrqRegistered=true\n"); -+ } while (0); -+ -+ if (iRetVal != IOH_SPI_SUCCESS) { -+ IOH_LOG(KERN_ERR, -+ "ioh_spi_get_resources FAIL:invoking\ -+ ioh_spi_free_resources\n"); -+ ioh_spi_free_resources(pBoardData); -+ } -+ -+ IOH_DEBUG("ioh_spi_get_resources Return=%d\n", iRetVal); -+ -+ return iRetVal; -+} -+ -+/*! @ingroup SPI_UtilitiesAPI -+ -+@fn ioh_spi_free_resources(struct ioh_spi_board_data* pBoardData) -+ -+@remarks Frees the resources acquired by IOH SPI driver -+ -+ The main tasks performed by this method are: -+ - Destroy the workqueus created for all SPI channels. -+ - Disables interrupts and unregisters the interrupt handler. -+ - Unmaps the PCI base address. -+ - Releases PCI regions. -+ -+@note This function is invoked from ioh_spi_remove when the SPI device is -+ being removed from the system or when the IOH SPI driver is being -+ unloaded from the system using "rmmod" command. -+ -+@param pBoardData [@ref INOUT] Contains the reference to struct -+ ioh_spi_board_data -+ -+@retval None -+ -+@see -+ - ioh_spi_remove -+ -+<hr> -+*/ -+void ioh_spi_free_resources(struct ioh_spi_board_data *pBoardData) -+{ -+ int i; -+ -+ IOH_DEBUG("ioh_spi_free_resources ENTRY\n"); -+ -+ /*free workqueue */ -+ -+ for (i = 0; i < IOH_SPI_MAX_DEV; i++) { -+ if (pBoardData->pCtrlData[i]->pWorkQueue != NULL) { -+ destroy_workqueue(pBoardData->pCtrlData[i]->pWorkQueue); -+ pBoardData->pCtrlData[i]->pWorkQueue = NULL; -+ IOH_DEBUG -+ ("ioh_spi_free_resources destroy_workqueue invoked\ -+ successfully\n"); -+ } -+ } -+ -+ /*disable interrupts & free IRQ */ -+ if (pBoardData->bIrqRegistered == true) { -+ /* disable interrupts */ -+ for (i = 0; i < IOH_SPI_MAX_DEV; i++) { -+ ioh_spi_disable_interrupts(pBoardData->pCtrlData[i]-> -+ pMaster, IOH_SPI_ALL); -+ IOH_DEBUG -+ ("ioh_spi_free_resources ioh_spi_disable_interrupts\ -+ invoked successfully\n"); -+ } -+ -+ /*free IRQ */ -+ free_irq(pBoardData->pDev->irq, (void *)pBoardData); -+ -+ IOH_DEBUG -+ ("ioh_spi_free_resources free_irq invoked successfully\n"); -+ -+ pBoardData->bIrqRegistered = false; -+ } -+ -+ /*unmap PCI base address */ -+ if ((pBoardData->pCtrlData[0]->IORemapAddress) != 0) { -+ pci_iounmap(pBoardData->pDev, -+ (void *)(pBoardData->pCtrlData[0]->IORemapAddress)); -+ -+ for (i = 0; i < IOH_SPI_MAX_DEV; i++) -+ pBoardData->pCtrlData[i]->IORemapAddress = 0; -+ -+ -+ IOH_DEBUG -+ ("ioh_spi_free_resources pci_iounmap invoked\ -+ successfully\n"); -+ } -+ -+ /*release PCI region */ -+ if (pBoardData->bRegionRequested == true) { -+ pci_release_regions(pBoardData->pDev); -+ IOH_DEBUG -+ ("ioh_spi_free_resources pci_release_regions invoked\ -+ successfully\n"); -+ pBoardData->bRegionRequested = false; -+ } -+} -+ -+/*! @ingroup SPI_UtilitiesAPI -+ -+@fn ioh_spi_process_messages(struct work_struct* pWork) -+ -+@remarks Work Queue handler to handle SPI data transfers -+ -+The main tasks performed by this method are: -+- If system is suspended,then flush the queue of pending transfers and return. -+- Retrieve the SPI message to be processed from the queue of pending messages. -+- Invoke @ref ioh_spi_select_chip to configure the SPI channel. -+- Retrieve the 1st or the subsequent transfer structure from SPI message -+ structure. -+- Update baud rate and bits per word,if user has specified new values. -+- Allocate memory for Transmit and Receive buffers. -+- Copy transmit data from transfer structure to Transmit buffer. -+- Pull down SSN by writing 0x2 to SSNXCR register. -+- Write transmit data to Transmit FIFO. -+- Enable required interrupts. -+- Enable SPI transfer by invoking @ref ioh_spi_set_enable. -+- Wait till SPI data transfer is completed. -+- Relinquish control over SSN by writing 0x0 to SSNXCR register. -+- Disable SPI transfer by invoking @ref ioh_spi_set_enable. -+- Clear Transmit & Receive FIFOs by invoking @ref ioh_spi_clear_fifo. -+- Copy received data from Receive buffer to transfer structure. -+- Free memory allocated for Transmit and Receive buffers. -+- Update data count in transfer structure. -+- If the SPI message has any more transfers , process them same as above. -+- If system is suspended,then flush the queue of pending transfers and return. -+- Again schedule the work queue haandler to run if there are pending messages in -+queue of pending messages. -+ -+@note Work Queue handler is scheduled by @ref ioh_spi_transfer after -+the SPI message to be processed is pushed into the queue of pending -+transfers.This function will write the first set of data to Tx FIFO and sleeps -+till all SPI data transfer is over.The data transfer is handled by -+the interrupt handler ioh_spi_handler function. -+ -+@param pWork [@ref IN] contains reference to struct work_struct -+ -+@retval None -+ -+@see -+ - ioh_spi_transfer -+ -+<hr> -+*/ -+static void ioh_spi_process_messages(struct work_struct *pWork) -+{ -+ int j; -+ u32 nWrites; -+ -+ struct spi_message *pMsg; -+ int bMemFail, size; -+ int bpw; -+ -+ struct ioh_spi_data *pCtrlData = -+ container_of(pWork, struct ioh_spi_data, Work); -+ IOH_DEBUG("ioh_spi_process_messages pCtrlData initialized\n"); -+ -+ spin_lock(&pCtrlData->Lock); -+ -+ /*check if suspend has been initiated;if yes flush queue */ -+ -+ if ((pCtrlData->pBoardData->bSuspended == true) -+ || (pCtrlData->Status == STATUS_EXITING)) { -+ IOH_DEBUG -+ ("ioh_spi_process_messages suspend/remove initiated,\ -+ flushing queue\n"); -+ list_for_each_entry(pMsg, pCtrlData->Queue.next, queue) { -+ pMsg->status = -EIO; -+ -+ if (pMsg->complete != 0) -+ pMsg->complete(pMsg->context); -+ -+ -+ /*delete from queue */ -+ list_del_init(&pMsg->queue); -+ } -+ -+ spin_unlock(&pCtrlData->Lock); -+ } else { -+ pCtrlData->bCurrent_msg_processing = true; -+ IOH_DEBUG -+ ("ioh_spi_process_messages set pCtrlData->\ -+ bCurrent_msg_processing" -+ "= true\n"); -+ -+ /*Get the message from the queue and delete it from there. */ -+ pCtrlData->pCurMsg = -+ list_entry(pCtrlData->Queue.next, struct spi_message, -+ queue); -+ IOH_DEBUG -+ ("ioh_spi_process_messages :Got new message from queue \n"); -+ list_del_init(&pCtrlData->pCurMsg->queue); -+ -+ pCtrlData->pCurMsg->status = 0; -+ -+ IOH_DEBUG -+ ("ioh_spi_process_messages :Invoking ioh_spi_select_chip\n"); -+ ioh_spi_select_chip(pCtrlData, pCtrlData->pCurMsg->spi); -+ -+ spin_unlock(&pCtrlData->Lock); -+ -+ do { -+ /*If we are already processing a message get the next -+ transfer -+ structure from the message otherwise retrieve the -+ 1st transfer -+ request from the message. */ -+ spin_lock(&pCtrlData->Lock); -+ -+ if (pCtrlData->pCurTransfer == NULL) { -+ pCtrlData->pCurTransfer = -+ list_entry(pCtrlData->pCurMsg->transfers. -+ next, struct spi_transfer, -+ transfer_list); -+ IOH_DEBUG -+ ("ioh_spi_process_messages :Getting 1st\ -+ transfer structure" -+ "for this message\n"); -+ } else { -+ pCtrlData->pCurTransfer = -+ list_entry(pCtrlData->pCurTransfer-> -+ transfer_list.next, -+ struct spi_transfer, -+ transfer_list); -+ IOH_DEBUG -+ ("ioh_spi_process_messages :Getting next\ -+ transfer structure" -+ "for this message\n"); -+ } -+ -+ spin_unlock(&pCtrlData->Lock); -+ -+ /*set baud rate if needed */ -+ -+ if (pCtrlData->pCurTransfer->speed_hz) { -+ IOH_DEBUG -+ ("ioh_spi_process_messages:setting\ -+ baud rate\n"); -+ ioh_spi_set_baud_rate(pCtrlData->pMaster, -+ (pCtrlData->pCurTransfer-> -+ speed_hz)); -+ } -+ -+ /*set bits per word if needed */ -+ if ((pCtrlData->pCurTransfer->bits_per_word) && -+ ((pCtrlData->pCurMsg->spi->bits_per_word) != -+ (pCtrlData->pCurTransfer->bits_per_word))) { -+ IOH_DEBUG -+ ("ioh_spi_process_messages:setting bits\ -+ per word\n"); -+ ioh_spi_set_bits_per_word(pCtrlData->pMaster, -+ (pCtrlData-> -+ pCurTransfer-> -+ bits_per_word)); -+ bpw = pCtrlData->pCurTransfer->bits_per_word; -+ } else { -+ bpw = pCtrlData->pCurMsg->spi->bits_per_word; -+ } -+ -+ /*reset Tx/Rx index */ -+ pCtrlData->TxIndex = 0; -+ -+ pCtrlData->RxIndex = 0; -+ -+ if (IOH_SPI_8_BPW == bpw) { -+ /*8 bits per word */ -+ pCtrlData->lengthInBpw = -+ pCtrlData->pCurTransfer->len; -+ } else { -+ /*16 bits per word */ -+ pCtrlData->lengthInBpw = -+ (pCtrlData->pCurTransfer->len) / 2; -+ } -+ -+ bMemFail = false; -+ -+ /*find alloc size */ -+ size = -+ (pCtrlData->pCurTransfer->len) * -+ (sizeof(*(pCtrlData->pU16TxBuffer))); -+ /*allocate memory for pU16TxBuffer & pU16RxBuffer */ -+ pCtrlData->pU16TxBuffer = -+/* (u16 *) kzalloc(size, GFP_KERNEL);*/ -+ kzalloc(size, GFP_KERNEL); -+ if (pCtrlData->pU16TxBuffer != NULL) { -+ pCtrlData->pU16RxBuffer = -+/* (u16 *) kzalloc(size, GFP_KERNEL);*/ -+ kzalloc(size, GFP_KERNEL); -+ if (pCtrlData->pU16RxBuffer == NULL) { -+ bMemFail = true; -+ kfree(pCtrlData->pU16TxBuffer); -+ } -+ } else { -+ bMemFail = true; -+ } -+ -+ if (bMemFail) { -+ /*flush queue and set status of all transfers -+ to -ENOMEM */ -+ IOH_LOG(KERN_ERR, -+ "Kzalloc fail in\ -+ ioh_spi_process_messages\n"); -+ list_for_each_entry(pMsg, pCtrlData->Queue.next, -+ queue) { -+ pMsg->status = -ENOMEM; -+ -+ if (pMsg->complete != 0) -+ pMsg->complete(pMsg->context); -+ -+ -+ /*delete from queue */ -+ list_del_init(&pMsg->queue); -+ } -+ -+ return; -+ } -+ -+ /*copy Tx Data */ -+ if ((pCtrlData->pCurTransfer->tx_buf) != NULL) { -+ for (j = 0; j < (pCtrlData->lengthInBpw); j++) { -+ if (IOH_SPI_8_BPW == bpw) { -+ pCtrlData->pU16TxBuffer[j] = -+ (((u8 *) (pCtrlData-> -+ pCurTransfer-> -+ tx_buf))[j]); -+ IOH_DEBUG -+ ("xmt data in\ -+ ioh_spi_process_messages=%x\n", -+ (pCtrlData-> -+ pU16TxBuffer[j])); -+ } else { -+ pCtrlData->pU16TxBuffer[j] = -+ ((u16 *) (pCtrlData-> -+ pCurTransfer-> -+ tx_buf))[j]; -+ IOH_DEBUG -+ ("xmt data ioh_spi_pro\ -+ cess_messages%x\n", -+ (pCtrlData-> -+ pU16TxBuffer[j])); -+ } -+ } -+ } -+ -+ /*if len greater than IOH_SPI_MAX_FIFO_DEPTH, -+ write 16,else len bytes */ -+ if ((pCtrlData->lengthInBpw) > IOH_SPI_MAX_FIFO_DEPTH) -+ nWrites = IOH_SPI_MAX_FIFO_DEPTH; -+ else -+ nWrites = (pCtrlData->lengthInBpw); -+ -+ -+#ifndef FPGA -+ /*LSI*/ -+ IOH_DEBUG -+ ("\nioh_spi_process_messages:Pulling down SSN low\ -+ - writing 0x2 to SSNXCR\n"); -+ ioh_spi_writereg(pCtrlData->pMaster, IOH_SPI_SSNXCR, -+ SSN_LOW); -+#endif -+ IOH_DEBUG -+ ("\nioh_spi_process_messages:Writing %u items\n", -+ nWrites); -+ -+ for (j = 0; j < nWrites; j++) { -+ ioh_spi_writereg(pCtrlData->pMaster, -+ IOH_SPI_SPDWR, -+ pCtrlData->pU16TxBuffer[j]); -+ } -+ -+ /*update TxIndex */ -+ pCtrlData->TxIndex = j; -+ -+ IOH_DEBUG -+ ("ioh_spi_process_messages:enabling interrupts\n"); -+ -+ /*reset transfer complete flag */ -+ pCtrlData->bTransferComplete = false; -+ -+ pCtrlData->bTransferActive = true; -+ -+ IOH_DEBUG -+ ("ioh_spi_process_messages set pCtrlData->\ -+ bTransferActive = true\n"); -+ -+ /*enable interrupts */ -+ if ((pCtrlData->lengthInBpw) > IOH_SPI_MAX_FIFO_DEPTH) { -+ /*set receive threhold to IOH_SPI_RX_THOLD */ -+ ioh_spi_set_threshold(pCtrlData->pCurrentChip, -+ IOH_SPI_RX_THOLD, -+ IOH_SPI_RX); -+ /*enable FI and RFI interrupts */ -+ ioh_spi_enable_interrupts(pCtrlData->pMaster, -+ IOH_SPI_RFI | -+ IOH_SPI_FI); -+ } else { -+ /*set receive threhold to maximum */ -+ ioh_spi_set_threshold(pCtrlData->pCurrentChip, -+ IOH_SPI_RX_THOLD_MAX, -+ IOH_SPI_RX); -+ /*enable FI interrupt */ -+ ioh_spi_enable_interrupts(pCtrlData->pMaster, -+ IOH_SPI_FI); -+ } -+ -+ IOH_DEBUG -+ ("ioh_spi_process_messages:invoking\ -+ ioh_spi_set_enable to enable SPI\n"); -+ -+ ioh_spi_set_enable((pCtrlData->pCurrentChip), true); -+ -+ /*Wait until the transfer completes; go to sleep -+ after initiating the transfer. */ -+ IOH_DEBUG -+ ("ioh_spi_process_messages:waiting for transfer\ -+ to get over\n"); -+ -+ wait_event_interruptible(pCtrlData->Wait, -+ false != -+ pCtrlData->bTransferComplete); -+#ifndef FPGA -+ /*LSI*/ -+ ioh_spi_writereg(pCtrlData->pMaster, IOH_SPI_SSNXCR, -+ SSN_NO_CONTROL); -+ IOH_DEBUG -+ ("\n ioh_spi_process_messages:no more control over\ -+ SSN-writing 0x0 to SSNXCR"); -+#endif -+ IOH_DEBUG("ioh_spi_process_messages:transmit over\n"); -+ -+ pCtrlData->bTransferActive = false; -+ IOH_DEBUG -+ ("ioh_spi_process_messages set pCtrlData->\ -+ bTransferActive = false\n"); -+ -+ /*clear all interrupts */ -+ ioh_spi_writereg(pCtrlData->pMaster, IOH_SPI_SPSR, -+ (ioh_spi_readreg -+ (pCtrlData->pMaster, IOH_SPI_SPSR))); -+ /*disable interrupts */ -+ ioh_spi_disable_interrupts(pCtrlData->pMaster, -+ IOH_SPI_ALL); -+ -+ /*Disable SPI transfer */ -+ IOH_DEBUG -+ ("ioh_spi_process_messages:invoking\ -+ ioh_spi_set_enable to disable" -+ "spi transfer\n"); -+ ioh_spi_set_enable((pCtrlData->pCurrentChip), false); -+ -+ /*clear FIFO */ -+ IOH_DEBUG -+ ("ioh_spi_process_messages:invoking\ -+ ioh_spi_clear_fifo to " -+ "clear fifo\n"); -+ ioh_spi_clear_fifo(pCtrlData->pMaster); -+ -+ /*copy Rx Data */ -+ -+ if ((pCtrlData->pCurTransfer->rx_buf) != NULL) { -+ for (j = 0; j < (pCtrlData->lengthInBpw); j++) { -+ if (IOH_SPI_8_BPW == bpw) { -+ ((u8 *) (pCtrlData-> -+ pCurTransfer-> -+ rx_buf))[j] = -+ (u8) ((pCtrlData-> -+ pU16RxBuffer[j]) & -+ 0xFF); -+ -+ IOH_DEBUG -+ ("rcv data in ioh_spi_proc\ -+ ess_messages=%x\n", -+ (pCtrlData-> -+ pU16RxBuffer[j])); -+ -+ } else { -+ ((u16 *) (pCtrlData-> -+ pCurTransfer-> -+ rx_buf))[j] = -+ (u16) (pCtrlData-> -+ pU16RxBuffer[j]); -+ IOH_DEBUG -+ ("rcv data in ioh_spi_proce\ -+ ss_messages=%x\n", -+ (pCtrlData-> -+ pU16RxBuffer[j])); -+ } -+ } -+ } -+ -+ /*free memory */ -+ kfree(pCtrlData->pU16RxBuffer); -+ pCtrlData->pU16RxBuffer = NULL; -+ -+ -+ kfree(pCtrlData->pU16TxBuffer); -+ pCtrlData->pU16TxBuffer = NULL; -+ -+ -+ /*increment message count */ -+ pCtrlData->pCurMsg->actual_length += -+ pCtrlData->pCurTransfer->len; -+ -+ IOH_DEBUG -+ ("ioh_spi_process_messages:pCtrlData->pCurMsg->\ -+ actual_length=%d\n", -+ pCtrlData->pCurMsg->actual_length); -+ -+ /*check for delay */ -+ if (pCtrlData->pCurTransfer->delay_usecs) { -+ IOH_DEBUG -+ ("ioh_spi_process_messages:delay in usec=%d\n", -+ pCtrlData->pCurTransfer->delay_usecs); -+ udelay(pCtrlData->pCurTransfer->delay_usecs); -+ } -+ -+ spin_lock(&pCtrlData->Lock); -+ -+ /*No more transfer in this message. */ -+ -+ if ((pCtrlData->pCurTransfer->transfer_list.next) == -+ &(pCtrlData->pCurMsg->transfers)) { -+ IOH_DEBUG -+ ("ioh_spi_process_messages:no more\ -+ transfers in this message\n"); -+ /*Invoke complete callback -+ [To the spi core..indicating -+ end of transfer] */ -+ pCtrlData->pCurMsg->status = 0; -+ -+ if ((pCtrlData->pCurMsg->complete) != 0) { -+ IOH_DEBUG -+ ("ioh_spi_process_messages:Invoking\ -+ callback of SPI core\n"); -+ pCtrlData->pCurMsg->complete(pCtrlData-> -+ pCurMsg-> -+ context); -+ } -+ -+ /*update status in global variable */ -+ pCtrlData->bCurrent_msg_processing = false; -+ -+ IOH_DEBUG -+ ("ioh_spi_process_messages:pCtrlData->\ -+ bCurrent_msg_processing" -+ "set to false\n"); -+ -+ pCtrlData->pCurMsg = NULL; -+ -+ pCtrlData->pCurTransfer = NULL; -+ -+ /*check if we have items in list and not -+ suspending */ -+ /*return 1 if list empty */ -+ if ((list_empty(&pCtrlData->Queue) == 0) && -+ (pCtrlData->pBoardData->bSuspended == false) -+ && (pCtrlData->Status != STATUS_EXITING)) { -+ /*We have some more work to do -+ (either there is more transfer -+ requests in the current message or -+ there are more messages) */ -+ IOH_DEBUG -+ ("ioh_spi_process_messages:we\ -+ have pending messages" -+ "-Invoking queue_work\n"); -+ queue_work(pCtrlData->pWorkQueue, -+ &pCtrlData->Work); -+ } -+ -+ /*check if suspend has been initiated;if yes -+ flush queue */ -+ else if ((pCtrlData->pBoardData->bSuspended == -+ true) -+ || (pCtrlData->Status == -+ STATUS_EXITING)) { -+ IOH_DEBUG -+ ("ioh_spi_process_messages\ -+ suspend/remove initiated," -+ "flushing queue\n"); -+ list_for_each_entry(pMsg, -+ pCtrlData->Queue. -+ next, queue) { -+ pMsg->status = -EIO; -+ -+ if (pMsg->complete != 0) { -+ pMsg->complete(pMsg-> -+ context); -+ } -+ -+ /*delete from queue */ -+ list_del_init(&pMsg->queue); -+ } -+ } -+ } -+ -+ spin_unlock(&pCtrlData->Lock); -+ -+ } while ((pCtrlData->pCurTransfer) != NULL); -+ } -+} -+ -+/*! @ingroup SPI_UtilitiesAPI -+ -+@fn ioh_spi_select_chip(struct ioh_spi_data* pCtrlData,struct spi_device* pSpi) -+ -+@remarks Update the SPI device details in the SPI channel data structure -+ -+The main tasks performed by this method are: -+- Check whether the active SPI device is different from the device to -+ which the previous data transfer occured. -+- If yes invoke @ref ioh_spi_deselect_chip to clear details of old device -+ from pCtrlData. -+- Update the details of the new device in pCtrlData -+- Invoke @ref ioh_spi_setup_transfer to configure the SPI channel. -+ -+@note This function is invoked by @ref ioh_spi_process_messages before -+ processing -+ each SPI message. -+ -+@param pCtrlData [@ref INOUT] contains reference to struct ioh_spi_data -+ -+@param pSpi [@ref IN] contains reference to struct spi_device -+ -+@retval None -+ -+@see -+ - ioh_spi_process_messages -+ -+<hr> -+*/ -+static inline void ioh_spi_select_chip(struct ioh_spi_data *pCtrlData, -+ struct spi_device *pSpi) -+{ -+ if ((pCtrlData->pCurrentChip) != NULL) { -+ if ((pSpi->chip_select) != (pCtrlData->nCurrentChip)) { -+ IOH_DEBUG -+ ("ioh_spi_select_chip : different slave-Invoking" -+ "ioh_spi_deselect_chip\n"); -+ ioh_spi_deselect_chip(pCtrlData); -+ } -+ } -+ -+ pCtrlData->pCurrentChip = pSpi; -+ -+ pCtrlData->nCurrentChip = pCtrlData->pCurrentChip->chip_select; -+ -+ IOH_DEBUG("ioh_spi_select_chip :Invoking ioh_spi_setup_transfer\n"); -+ ioh_spi_setup_transfer(pSpi); -+} -+ -+/*! @ingroup SPI_UtilitiesAPI -+ -+@fn ioh_spi_deselect_chip(struct ioh_spi_data* pCtrlData) -+ -+@remarks Clear the SPI device details from the SPI channel data structure -+ -+ The main tasks performed by this method are: -+ - Clear the details of SPI device from SPI channel data structure. -+ -+@note This function is invoked from @ref ioh_spi_select_chip -+ -+@param pCtrlData [@ref INOUT] Contains reference to struct ioh_spi_data -+ -+@retval None -+ -+@see -+ - ioh_spi_select_chip -+ -+<hr> -+*/ -+static inline void ioh_spi_deselect_chip(struct ioh_spi_data *pCtrlData) -+{ -+ if (pCtrlData->pCurrentChip != NULL) { -+ IOH_DEBUG -+ ("ioh_spi_deselect_chip :clearing pCurrentChip data\n"); -+ pCtrlData->pCurrentChip = NULL; -+ } -+} -+ -+/*! @ingroup SPI_UtilitiesAPI -+ -+@fn ioh_spi_check_request_pending(struct ioh_spi_board_data* pBoardData) -+ -+@remarks Checks for any pending SPI transfer request in the queue of -+ pending transfers -+ -+ The main tasks performed by this method are: -+ - If the message queue is empty return IOH_SPI_SUCCESS. -+ - Sleep for 100ms and again check if message queue is empty,if yes -+ return IOH_SPI_SUCCESS. -+ - Repeat 500 times. -+ - If queue is still not empty return -EBUSY. -+ -+@note This function is invoked by @ref ioh_spi_remove -+ -+@param pBoardData [@ref INOUT] Contains reference to struct -+ ioh_spi_board_data -+ -+@retval int -+ - @ref IOH_SPI_SUCCESS Message queue is empty -+ - -EBUSY Queue is not empty -+ -+@see -+ - ioh_spi_remove -+ -+<hr> -+*/ -+int ioh_spi_check_request_pending(struct ioh_spi_board_data *pBoardData) -+{ -+ int i; -+ int iStatus = IOH_SPI_SUCCESS; -+ u16 count; -+ -+ for (i = 0; i < IOH_SPI_MAX_DEV; i++) { -+ count = 500; -+ spin_lock(&(pBoardData->pCtrlData[i]->Lock)); -+ pBoardData->pCtrlData[i]->Status = STATUS_EXITING; -+ -+ while ((list_empty(&(pBoardData->pCtrlData[i]->Queue)) == 0) && -+ (--count)) { -+ IOH_DEBUG -+ ("ioh_spi_check_request_pending :Queue not empty\n"); -+ spin_unlock(&(pBoardData->pCtrlData[i]->Lock)); -+ msleep(IOH_SPI_SLEEP_TIME); -+ spin_lock(&(pBoardData->pCtrlData[i]->Lock)); -+ } -+ -+ spin_unlock(&(pBoardData->pCtrlData[i]->Lock)); -+ -+ if (count) { -+ IOH_DEBUG -+ ("ioh_spi_check_request_pending :Queue empty\n"); -+ } else { -+ iStatus = -EBUSY; -+ } -+ } -+ -+ IOH_DEBUG("ioh_spi_check_request_pending : EXIT=%d\n", iStatus); -+ -+ return iStatus; -+} -+ -+/*! @ingroup SPI_InterfaceLayerAPI -+ -+@fn int ioh_spi_setup(struct spi_device* pSpi) -+ -+@remarks Validates the SPI device configuration paramters specified by user -+ -+The main tasks performed by this method are: -+- Validate the bits per word paramter (should be either 8 or 16). -+- Validate the maximum baud rate parameter (should not be greater than 5Mbps). -+ -+@note This function is registered with the SPI core as the setup routine of -+IOH SPI controller driver.This function is invoked by the kernel SPI -+component when user invokes any of spidev's IOCTLs to configure the -+SPI device setting.In this function no hardware settings are modified -+as this can affect any ongoing SPI data transfers.So the setting passed -+by the user is validated and the function returns.Hardware settings are -+updated in the function @ref ioh_spi_setup_transfer, which is invoked from -+@ref ioh_spi_process_messages before initiating a SPI data transfer. -+ -+@param pSpi [@ref IN] Contains reference to structure spi_device -+ -+@retval int -+ - IOH_SPI_SUCCESS All paramters are valid -+ - -EINVAL Any of the paramter is invalid -+ -+@see -+ - ioh_spi_probe -+ -+<hr> -+*/ -+int ioh_spi_setup(struct spi_device *pSpi) -+{ -+ int iRetVal = IOH_SPI_SUCCESS; -+ -+ /*check bits per word */ -+ -+ if ((pSpi->bits_per_word) == 0) { -+ pSpi->bits_per_word = IOH_SPI_8_BPW; -+ IOH_DEBUG("ioh_spi_setup 8 bits per word \n"); -+ } -+ -+ if (((pSpi->bits_per_word) != IOH_SPI_8_BPW) && -+ ((pSpi->bits_per_word != IOH_SPI_16_BPW))) { -+ IOH_LOG(KERN_ERR, "ioh_spi_setup Invalid bits per word\n"); -+ iRetVal = -EINVAL; -+ } -+ -+ /*Check baud rate setting */ -+ /*if baud rate of chip is greater than -+ max we can support,return error */ -+ if ((pSpi->max_speed_hz) > IOH_SPI_MAX_BAUDRATE) { -+ iRetVal = -EINVAL; -+ IOH_LOG(KERN_ERR, "ioh_spi_setup Invalid Baud rate\n"); -+ } -+ -+ IOH_DEBUG(KERN_ERR, "ioh_spi_setup MODE = %x\n", -+ ((pSpi->mode) & (SPI_CPOL | SPI_CPHA))); -+ -+ if (((pSpi->mode) & SPI_LSB_FIRST) != 0) -+ IOH_DEBUG("ioh_spi_setup LSB_FIRST\n"); -+ else -+ IOH_DEBUG("ioh_spi_setup MSB_FIRST\n"); -+ -+ -+ IOH_DEBUG("ioh_spi_setup Return=%d\n", iRetVal); -+ -+ return iRetVal; -+} -+ -+/*! @ingroup SPI_InterfaceLayerAPI -+ -+@fn ioh_spi_transfer(struct spi_device* pSpi,struct spi_message* pMsg) -+ -+@remarks Validates the SPI message and pushes it onto queue of pending -+ transfers -+ -+ The main tasks performed by this method are: -+ - If the list of transfers is empty return -EINVAL. -+ - If the maximum baud rate is zero return -EINVAL. -+ - If Tranmit buffer and Receive buffer both are invalid for -+ any transfer return -EINVAL. -+ - If the length of transfer is zero for any transfer return -EINVAL. -+ - If maximum baud rate and bits per word are invalid return -EINVAL. -+ - If status of SPI channel is STATUS_EXITING return -ESHUTDOWN. -+ - If device is suspended return -EINVAL. -+ - Add the SPI message to queue of pending SPI messages. -+ - Schedule work queue handler to run. -+ -+@note ioh_spi_transfer is registered by IOH SPI controller driver -+ with SPI core as -+ its transfer routine from the function @ref ioh_spi_probe.It -+ is invoked by the kernel's SPI component when user invokes -+ read,write or SPI_IOC_MESSAGE ioctl. -+ -+@param pSpi [@ref IN] Contains reference to struct spi_device -+ -+@param pMsg [@ref IN] Contains reference to struct spi_message -+ -+@retval int -+- @ref IOH_SPI_SUCCESS The function exists normally after adding the SPI message -+ to queue of pending SPI messages and schedules work queue -+ handler to run. -+- -EINVAL Any of the paramters are found to be invalid or the system is -+ suspended. -+- -ESHUTDOWN When the status of the SPI channel is STATUS_EXITING -+ The status STATUS_EXITING is set when ioh_spi_remove -+ is invoked. -+ -+@see -+ - ioh_spi_probe -+ -+<hr> -+*/ -+int ioh_spi_transfer(struct spi_device *pSpi, struct spi_message *pMsg) -+{ -+ -+ struct spi_transfer *pTransfer; -+ -+ struct ioh_spi_data *pCtrlData = spi_master_get_devdata(pSpi->master); -+ int iRetVal = IOH_SPI_SUCCESS; -+ -+ do { -+ /*validate spi message and baud rate */ -+ if (unlikely((list_empty(&pMsg->transfers) == 1) || -+ ((pSpi->max_speed_hz) == 0))) { -+ if (list_empty(&pMsg->transfers) == 1) { -+ IOH_LOG(KERN_ERR, -+ "ioh_spi_transfer list empty\n"); -+ } -+ -+ if ((pSpi->max_speed_hz) == 0) { -+ IOH_LOG(KERN_ERR, -+ "ioh_spi_tranfer maxspeed=%d\n", -+ (pSpi->max_speed_hz)); -+ } -+ -+ IOH_LOG(KERN_ERR, -+ "ioh_spi_transfer returning EINVAL\n"); -+ -+ iRetVal = -EINVAL; -+ break; -+ } -+ -+ IOH_DEBUG("ioh_spi_transfer Transfer List not empty\n"); -+ -+ IOH_DEBUG("ioh_spi_transfer Transfer Speed is set\n"); -+ -+ /*validate Tx/Rx buffers and Transfer length */ -+ list_for_each_entry(pTransfer, &pMsg->transfers, -+ transfer_list) { -+ if ((((pTransfer->tx_buf) == NULL) -+ && ((pTransfer->rx_buf) == NULL)) -+ || (pTransfer->len == 0)) { -+ if (((pTransfer->tx_buf) == NULL) -+ && ((pTransfer->rx_buf) == NULL)) { -+ IOH_LOG(KERN_ERR, -+ "ioh_spi_transfer Tx and Rx\ -+ buffer NULL\n"); -+ } -+ -+ if (pTransfer->len == 0) { -+ IOH_LOG(KERN_ERR, -+ "ioh_spi_transfer Transfer\ -+ length invalid\n"); -+ } -+ -+ IOH_LOG(KERN_ERR, -+ "ioh_spi_transfer returning EINVAL\n"); -+ -+ iRetVal = -EINVAL; -+ break; -+ } -+ -+ IOH_DEBUG("ioh_spi_transfer Tx/Rx buffer valid\n"); -+ -+ IOH_DEBUG("ioh_spi_transfer Transfer length valid\n"); -+ -+ /*if baud rate hs been specified validate the same */ -+ -+ if (pTransfer->speed_hz) { -+ if ((pTransfer->speed_hz) > -+ IOH_SPI_MAX_BAUDRATE) { -+ iRetVal = -EINVAL; -+ IOH_LOG(KERN_ERR, -+ "ioh_spi_transfer Invalid\ -+ Baud rate\n"); -+ } -+ } -+ -+ /*if bits per word has been specified validate -+ the same */ -+ if (pTransfer->bits_per_word) { -+ if ((pTransfer->bits_per_word != IOH_SPI_8_BPW) -+ && (pTransfer->bits_per_word != -+ IOH_SPI_16_BPW)) { -+ iRetVal = -EINVAL; -+ IOH_LOG(KERN_ERR, -+ "ioh_spi_transfer Invalid bits\ -+ per word\n"); -+ break; -+ } -+ } -+ } -+ -+ if (iRetVal == -EINVAL) -+ break; -+ -+ -+ spin_lock(&pCtrlData->Lock); -+ -+ /*We won't process any messages if we have been asked -+ to terminate */ -+ -+ if (STATUS_EXITING == (pCtrlData->Status)) { -+ spin_unlock(&pCtrlData->Lock); -+ IOH_LOG(KERN_ERR, -+ "ioh_spi_transfer -pCtrlData->Status\ -+ = STATUS_EXITING" -+ "returning ESHUTDOWN\n"); -+ iRetVal = -ESHUTDOWN; -+ break; -+ } -+ -+ /*If suspended ,return -EINVAL */ -+ if (pCtrlData->pBoardData->bSuspended == true) { -+ IOH_LOG(KERN_ERR, -+ "ioh_spi_transfer pCtrlData->\ -+ pBoardData->bSuspending" -+ "= true returning EINVAL\n"); -+ spin_unlock(&pCtrlData->Lock); -+ iRetVal = -EINVAL; -+ break; -+ } -+ -+ /*set status of message */ -+ pMsg->actual_length = 0; -+ -+ IOH_DEBUG -+ ("ioh_spi_transfer - setting pMsg->status = -EINPROGRESS\n"); -+ -+ pMsg->status = -EINPROGRESS; -+ -+ /*add message to queue */ -+ list_add_tail(&pMsg->queue, &pCtrlData->Queue); -+ -+ IOH_DEBUG("ioh_spi_transfer - Invoked list_add_tail\n"); -+ -+ /*schedule work queue to run */ -+ queue_work(pCtrlData->pWorkQueue, &pCtrlData->Work); -+ -+ IOH_DEBUG("ioh_spi_transfer - Invoked Queue Work\n"); -+ -+ spin_unlock(&pCtrlData->Lock); -+ -+ } while (0); -+ -+ IOH_DEBUG("ioh_spi_transfer RETURN=%d\n", iRetVal); -+ -+ return iRetVal; -+} -+ -+/*! @ingroup SPI_InterfaceLayerAPI -+ -+@fn ioh_spi_cleanup(struct spi_device* pSpi) -+ -+@remarks Provides the Cleanup routine for IOH SPI driver -+ -+@note This is a dummy function. -+ It is not mandatory to have a cleanup function. -+ If SPI master provides a cleanup function while they register -+ with the SPI core, then SPI core invokes the cleanup function -+ when SPI master calls spi_unregister_master function.This -+ driver invokes spi_unregister_master from ioh_spi_remove -+ function. Before invoking spi_unregister_master all the resources -+ used is freed i.e. cleanup activities are handled in the -+ @ref ioh_spi_remove function itself.This function is registered -+ as the cleanup routine for this SPI controller driver from -+ the @ref ioh_spi_probe function. -+ -+@param pSpi [@ref IN] Contains reference to struct spi_device -+ -+@retval None -+ -+@see -+ - ioh_spi_probe -+ -+<hr> -+ -+*/ -+void ioh_spi_cleanup(struct spi_device *pSpi) -+{ -+ IOH_DEBUG("spi_cleanup\n"); -+} -+ -+/*! @ingroup SPI_UtilitiesAPI -+ -+@fn ioh_spi_callback( struct ioh_spi_data* pCtrlData) -+ -+@remarks Informs ioh_spi_process_messages that SPI data transfer is complete -+ -+ The main tasks performed by this method are: -+ - Set transfer status of the SPI channel to completed. -+ - Inform this to @ref ioh_spi_process_messages. -+ -+@note The reference to this callback function is saved in a global pointer -+by the function @ref ioh_spi_entcb invoked from @ref ioh_spi_probe function. -+This function is invoked by the interrupt handler ioh_spi_handler -+after transfer complete interrupt is received indicating the end of -+SPI data transfer.ioh_spi_callback wakes up ioh_spi_process_messages -+which blocks till SPI data transfer is completed. -+ -+@param pCtrldata [@ref IN] Contains reference to struct ioh_spi_data -+ -+@retval None -+ -+@see -+ - ioh_spi_handler -+ - ioh_spi_probe -+ -+<hr> -+*/ -+void ioh_spi_callback(struct ioh_spi_data *pCtrlData) -+{ -+ IOH_DEBUG("ioh_ spi _callback waking up process\n"); -+ spin_lock(&pCtrlData->Lock); -+ pCtrlData->bTransferComplete = true; -+ wake_up(&pCtrlData->Wait); -+ IOH_DEBUG("ioh_ spi _callback invoked wake_up\n"); -+ spin_unlock(&pCtrlData->Lock); -+} -diff -urN linux-2.6.33-rc3/drivers/spi/pch_spi_pci.c topcliff-2.6.33-rc3/drivers/spi/pch_spi_pci.c ---- linux-2.6.33-rc3/drivers/spi/pch_spi_pci.c 1970-01-01 09:00:00.000000000 +0900 -+++ topcliff-2.6.33-rc3/drivers/spi/pch_spi_pci.c 2010-03-17 20:05:19.000000000 +0900 -@@ -0,0 +1,811 @@ -+/** -+ * @file ioh_spi_pci.c -+ * -+ * @brief This file contains the function definition for the PCI Layer APIs -+ * -+ * @version 0.94 -+ * -+ * @par -+ * -- Copyright Notice -- -+ * -+ * @par -+ * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD. -+ * All rights reserved. -+ * -+ * @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. -+ * -+ * @par -+ * -- End of Copyright Notice -- -+ */ -+ -+/*includes*/ -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/device.h> -+#include <linux/spi/spi.h> -+#include <linux/workqueue.h> -+#include <linux/delay.h> -+#include <linux/ioport.h> -+#include <linux/interrupt.h> -+/*#include <asm/io.h> modify by checkpatch.pl*/ -+#include <linux/io.h> -+#include "pch_spi.h" -+#include "pch_spi_hal.h" -+#include "pch_debug.h" -+ -+/*! @ingroup SPI_PCILayer -+ -+@def IOH_SPI_MAX_CS -+ -+@brief Denotes the maximum chip select number possible. -+ -+@note Currently this is just used to set the number of chip selects in -+ spi_master structure in @ref ioh_spi_probe function. -+ -+@see ioh_spi_probe -+ -+<hr> -+ -+*/ -+#define IOH_SPI_MAX_CS (0xFF) -+ -+/*pci device ids*/ -+ -+/*! @ingroup SPI_PCILayer -+ -+@brief Denotes the PCI device ID of the supported device. -+ -+@see ioh_spi_pcidev_id -+ -+<hr> -+ -+*/ -+#ifndef FPGA -+#define PCI_DEVICE_ID_IOH_SPI (0x8816) /*LSI*/ -+#else -+#define PCI_DEVICE_ID_IOH_SPI (0x8005) /*FPGA*/ -+#endif -+/*! @ingroup SPI_PCILayerAPI -+ -+@fn ioh_spi_probe(struct pci_dev *pDev, const struct pci_device_id *id) -+ -+@brief Implements the Probe functionality for IOH SPI driver -+ -+@remarks Implements the Probe functionality for IOH SPI driver -+ -+ The major tasks performed by this method are: -+ - Register the callback function. -+ - Enable the PCI device. -+ - Allocate memory for SPI master. -+ - Initialize members of SPI master structure. -+ - Register the SPI master. -+ - Invoke @ref ioh_spi_get_resources to acquire and initialize -+ other resources needed by the driver. -+ -+@note This function is invoked by the kernel when it detects -+ a SPI device matching the vendor ID and device ID specified -+ by this driver. -+ -+@param pDev [@ref INOUT] contains reference to struct pci_dev -+ -+@param id [@ref IN] contains reference to struct pci_device_id -+ -+@retval int -+- @ref IOH_SPI_SUCCESS The function exists successfully -+- -ENOMEM spi_alloc_master API fails/kmalloc fails -+- -EINVAL pci_enable_device fails/spi_register_master fails -+ /ioh_spi_get_resources fails -+- -EIO pci_enable_device fails -+- -ENODEV spi_register_master API fails -+- -ENOSYS ioh_spi_get_resources fails -+- -ENOMEM ioh_spi_get_resources fails -+ -+@see ioh_spi_pcidev -+ -+<hr> -+ -+*/ -+static int ioh_spi_probe(struct pci_dev *pDev, const struct pci_device_id *id) -+{ -+ -+ struct spi_master *pMaster[IOH_SPI_MAX_DEV]; -+ -+ struct ioh_spi_board_data *pBoardData; -+ int iRetVal, i, j; -+ -+ IOH_DEBUG("ioh_spi_probe ENTRY\n"); -+ /*initialize the call back function */ -+ ioh_spi_entcb(ioh_spi_callback); -+ IOH_DEBUG("ioh_spi_probe invoked ioh_spi_entcb\n"); -+ -+ do { -+ /*allocate memory for private data */ -+ pBoardData = -+ kmalloc(sizeof(struct ioh_spi_board_data), GFP_KERNEL); -+ -+ if (pBoardData == NULL) { -+ IOH_LOG(KERN_ERR, -+ " ioh_spi_probe memory allocation for private\ -+ data failed\n"); -+ iRetVal = -ENOMEM; -+ break; -+ } -+ -+ IOH_DEBUG -+ (" ioh_spi_probe memory allocation for private data\ -+ success\n"); -+ -+ /*enable PCI device */ -+ iRetVal = pci_enable_device(pDev); -+ if (iRetVal != 0) { -+ IOH_LOG(KERN_ERR, -+ "ioh_spi_probe pci_enable_device FAILED\n"); -+ -+ IOH_LOG(KERN_ERR, -+ "ioh_spi_probe invoked kfree to free memory\ -+ allocated for pBoardData\n"); -+ kfree(pBoardData); -+ break; -+ } -+ -+ IOH_DEBUG("ioh_spi_probe pci_enable_device returned=%d\n", -+ iRetVal); -+ -+ pBoardData->pDev = pDev; -+ -+ /*alllocate memory for SPI master */ -+ i = 0; -+ -+ do { -+ pMaster[i] = -+ spi_alloc_master(&pDev->dev, -+ sizeof(struct ioh_spi_data)); -+ -+ if (pMaster[i] == NULL) { -+ iRetVal = -ENOMEM; -+ -+ if (i > 0) { -+ j = 0; -+ -+ do { -+ spi_master_put(pMaster[j]); -+ j++; -+ IOH_DEBUG -+ ("ioh_spi_probe invoked\ -+ spi_master_put\n"); -+ } while (j < i); -+ } -+ -+ IOH_LOG(KERN_ERR, -+ "ioh_spi_probe spi_alloc_master\ -+ failed\n"); -+ -+ break; -+ } -+ -+ i++; -+ } while (i < IOH_SPI_MAX_DEV); -+ -+ IOH_DEBUG("ioh_spi_probe spi_alloc_master returned non NULL\n"); -+ -+ if (iRetVal != 0) { -+ kfree(pBoardData); -+ IOH_LOG(KERN_ERR, -+ "ioh_spi_probe invoked kfree to free memory\ -+ allocated for pBoardData\n"); -+ pci_disable_device(pDev); -+ IOH_LOG(KERN_ERR, -+ "ioh_spi_probe Invoked pci_disable_device\n"); -+ break; -+ } -+ -+ /*initialize members of SPI master */ -+ for (i = 0; i < IOH_SPI_MAX_DEV; i++) { -+ pMaster[i]->bus_num = i; -+ pMaster[i]->num_chipselect = IOH_SPI_MAX_CS; -+ pMaster[i]->setup = ioh_spi_setup; -+ IOH_DEBUG -+ ("ioh_spi_probe setup member of SPI master\ -+ initialized\n"); -+ pMaster[i]->transfer = ioh_spi_transfer; -+ IOH_DEBUG -+ ("ioh_spi_probe transfer member of SPI master\ -+ initialized\n"); -+ pMaster[i]->cleanup = ioh_spi_cleanup; -+ IOH_DEBUG -+ ("ioh_spi_probe cleanup member of SPI master\ -+ initialized\n"); -+ -+ pBoardData->pCtrlData[i] = -+ spi_master_get_devdata(pMaster[i]); -+ -+ pBoardData->pCtrlData[i]->pMaster = pMaster[i]; -+ pBoardData->pCtrlData[i]->nCurrentChip = 255; -+ pBoardData->pCtrlData[i]->pCurrentChip = NULL; -+ pBoardData->pCtrlData[i]->bTransferComplete = false; -+ pBoardData->pCtrlData[i]->pU16TxBuffer = NULL; -+ pBoardData->pCtrlData[i]->pU16RxBuffer = NULL; -+ pBoardData->pCtrlData[i]->TxIndex = 0; -+ pBoardData->pCtrlData[i]->RxIndex = 0; -+ pBoardData->pCtrlData[i]->bTransferActive = false; -+ pBoardData->pCtrlData[i]->pBoardData = pBoardData; -+ -+ /*Register the controller with the SPI core. */ -+ iRetVal = spi_register_master(pMaster[i]); -+ if (iRetVal != 0) { -+ spi_master_put(pMaster[i]); -+ IOH_DEBUG -+ ("ioh_spi_probe invoked spi_master_put\n"); -+ /*unregister master for any channel that has -+ registered master */ -+ -+ if (i > 0) { -+#if 0 -+ for (j = 0; j < i; j++) { -+ spi_unregister_master(pMaster -+ [j]); -+ IOH_DEBUG -+ ("ioh_spi_probe invoked\ -+ spi_unregister_master\n"); -+ } -+#else -+ spi_unregister_master(pMaster[0]); -+ IOH_DEBUG -+ ("ioh_spi_probe invoked\ -+ spi_unregister_master\n"); -+#endif -+ } -+ -+ IOH_LOG(KERN_ERR, -+ "ioh_spi_probe spi_register_\ -+ master FAILED\n"); -+ -+ break; -+ } -+ -+ IOH_DEBUG -+ ("ioh_spi_probe spi_register_master\ -+ returned=%d\n", -+ iRetVal); -+ } -+ -+ if (iRetVal != 0) { -+ kfree(pBoardData); -+ IOH_LOG(KERN_ERR, -+ "ioh_spi_probe invoked kfree to free memory\ -+ allocated for pBoardData\n"); -+ pci_disable_device(pDev); -+ IOH_DEBUG("ioh_spi_probe invoked pci_disable\n"); -+ break; -+ } -+ -+ /*allocate resources for IOH SPI */ -+ iRetVal = ioh_spi_get_resources(pBoardData); -+ if (iRetVal != IOH_SPI_SUCCESS) { -+ /* -+ for (i = 0; i < IOH_SPI_MAX_DEV; i++) { -+ spi_unregister_master(pMaster[i]); -+ IOH_DEBUG -+ ("ioh_spi_probe invoked\ -+ spi_unregister_master\n"); -+ } -+ */ -+ spi_unregister_master(pMaster[0]); -+ IOH_DEBUG -+ ("ioh_spi_probe invoked spi_unregister_master\n"); -+ -+ -+ kfree(pBoardData); -+ -+ IOH_LOG(KERN_ERR, -+ "ioh_spi_probe invoked kfree to free memory\ -+ allocated for pBoardData\n"); -+ pci_disable_device(pDev); -+ IOH_DEBUG("ioh_spi_probe invoked pci_disable\n"); -+ IOH_LOG(KERN_ERR, -+ "ioh_spi_probe get_resources FAILED\n"); -+ break; -+ } -+ -+ IOH_DEBUG("ioh_spi_probe ioh_spi_get_resources returned=%d\n", -+ iRetVal); -+ -+ /*save private data in dev */ -+ pci_set_drvdata(pDev, (void *)pBoardData); -+ IOH_DEBUG("ioh_spi_probe invoked pci_set_drvdata\n"); -+ -+ /*set master mode */ -+ -+ for (i = 0; i < IOH_SPI_MAX_DEV; i++) { -+ ioh_spi_set_master_mode(pMaster[i]); -+ IOH_DEBUG -+ ("ioh_spi_probe invoked ioh_spi_set_master_mode\n"); -+ } -+ -+ iRetVal = IOH_SPI_SUCCESS; -+ -+ } while (false); -+ -+ IOH_DEBUG("ioh_spi_probe Return=%d\n", iRetVal); -+ -+ return iRetVal; -+} -+ -+/*! @ingroup SPI_PCILayerAPI -+ -+@fn ioh_spi_remove(struct pci_dev *pDev) -+ -+@brief Implements the remove routine for IOH SPI driver -+ -+@remarks Implements the remove routine for IOH SPI driver -+ -+ The major tasks performed by this method are: -+ - Invoke @ref ioh_spi_check_request_pending function to find -+ out if there are any pending requests. -+ - Free the allocated resources by invoking @ref ioh_spi_free_resources. -+ - Unregister SPI master. -+ - Disable PCI device. -+ -+@note This function is invoked when the IOH SPI controller driver module -+ is removed from the system using "rmmod" command OR when the SPI -+ device is removed from the system. -+ -+@param pDev [@ref INOUT] contains reference to struct pci_dev -+ -+@retval None -+ -+@see ioh_spi_pcidev -+ -+<hr> -+ -+*/ -+static void ioh_spi_remove(struct pci_dev *pDev) -+{ -+ struct ioh_spi_board_data *pBoardData = pci_get_drvdata(pDev); -+ -+ IOH_DEBUG("ioh_spi_remove ENTRY\n"); -+ -+ if (pBoardData != NULL) { -+ IOH_DEBUG("ioh_spi_remove invoked pci_get_drvdata\n"); -+ -+ /*check for any pending messages */ -+ -+ if ((-EBUSY) == ioh_spi_check_request_pending(pBoardData)) { -+ IOH_DEBUG -+ ("ioh_spi_remove ioh_spi_check_request_pending\ -+ returned EBUSY\n"); -+ /*no need to take any particular action;proceed with -+ remove even -+ though queue is not empty */ -+ } -+ -+ IOH_DEBUG -+ ("ioh_spi_remove ioh_spi_check_request_pending invoked\n"); -+ -+ /*Free resources allocated for IOH SPI */ -+ ioh_spi_free_resources(pBoardData); -+ IOH_DEBUG("ioh_spi_remove invoked ioh_spi_free_resources\n"); -+ -+ /*Unregister SPI master */ -+ -+#if 0 -+ int i; -+ for (i = 0; i < IOH_SPI_MAX_DEV; i++) { -+ spi_unregister_master(pBoardData->pCtrlData[i]-> -+ pMaster); -+ IOH_DEBUG -+ ("ioh_spi_remove invoked spi_unregister_master\n"); -+ } -+#else -+ spi_unregister_master(pBoardData->pCtrlData[0]->pMaster); -+ IOH_DEBUG("ioh_spi_remove invoked spi_unregister_master\n"); -+ -+#endif -+ -+ /*free memory for private data */ -+ kfree(pBoardData); -+ -+ pci_set_drvdata(pDev, NULL); -+ -+ IOH_DEBUG("ioh_spi_remove memory for private data freed\n"); -+ -+ /*disable PCI device */ -+ pci_disable_device(pDev); -+ -+ IOH_DEBUG("ioh_spi_remove invoked pci_disable_device\n"); -+ -+ } else { -+ IOH_LOG(KERN_ERR, -+ "ioh_spi_remove pci_get_drvdata returned NULL\n"); -+ } -+} -+ -+/*! @ingroup SPI_PCILayerAPI -+ -+@fn ioh_spi_suspend(struct pci_dev *pDev,pm_message_t state) -+ -+@brief Implements the suspend routine for IOH SPI driver -+ -+@remarks Implements the suspend routine for IOH SPI driver -+ -+ The major tasks performed by this method are: -+ - Wait till current message is processed. -+ - Disable interrupts by invoking @ref ioh_spi_disable_interrupts. -+ - Unregister the interrupt handler. -+ - Save current state. -+ - Disable PM notifications. -+ - Disable PCI device. -+ - Move the device to D3Hot power state. -+ -+@note This function is invoked by the kernel when the system transitions -+ to low power state. -+ -+@param pDev [@ref INOUT] contains reference to struct pci_dev -+ -+@param state [@ref IN] contains new PM state to which to transition to. -+ -+@retval int -+ - @ref IOH_SPI_SUCCESS The function returns successfully -+ - -ENOMEM pci_save_state fails -+ -+@see ioh_spi_pcidev -+ -+<hr> -+ -+*/ -+#ifdef CONFIG_PM -+static int ioh_spi_suspend(struct pci_dev *pDev, pm_message_t state) -+{ -+ int i; -+ u8 count; -+ s32 iRetVal = IOH_SPI_SUCCESS; -+ -+ struct ioh_spi_board_data *pBoardData = pci_get_drvdata(pDev); -+ -+ IOH_DEBUG("ioh_spi_suspend ENTRY\n"); -+ -+ if (pBoardData == NULL) { -+ IOH_LOG(KERN_ERR, -+ "ioh_spi_suspend pci_get_drvdata returned NULL\n"); -+ iRetVal = -EFAULT; -+ } else { -+ IOH_DEBUG -+ ("ioh_spi_suspend pci_get_drvdata invoked successfully\n"); -+ pBoardData->bSuspended = true; -+ IOH_DEBUG -+ ("ioh_spi_suspend pBoardData->bSuspending set to true\n"); -+ -+ /*check if the current message is processed: -+ Only after thats done the transfer will be suspended */ -+ -+ for (i = 0; i < IOH_SPI_MAX_DEV; i++) { -+ count = 255; -+ -+ while ((--count) > 0) { -+ if (pBoardData->pCtrlData[i]-> -+ bCurrent_msg_processing == false) { -+ IOH_DEBUG -+ ("ioh_spi_suspend pBoardData\ -+ ->pCtrlData->" -+ "bCurrent_msg_processing\ -+ = false\n"); -+ break; -+ } else { -+ IOH_DEBUG -+ ("ioh_spi_suspend pBoardData\ -+ ->pCtrlData->" -+ "bCurrent_msg_processing = true\n"); -+ } -+ -+ msleep(IOH_SPI_SLEEP_TIME); -+ } -+ } -+ -+ /*Free IRQ */ -+ if (pBoardData->bIrqRegistered == true) { -+ /*disable all interrupts */ -+ for (i = 0; i < IOH_SPI_MAX_DEV; i++) { -+ ioh_spi_disable_interrupts(pBoardData-> -+ pCtrlData[i]-> -+ pMaster, -+ IOH_SPI_ALL); -+ ioh_spi_reset(pBoardData->pCtrlData[i]-> -+ pMaster); -+ IOH_DEBUG -+ ("ioh_spi_suspend ioh_spi_\ -+ disable_interrupts invoked" -+ "successfully\n"); -+ } -+ -+ free_irq(pBoardData->pDev->irq, (void *)pBoardData); -+ -+ pBoardData->bIrqRegistered = false; -+ IOH_DEBUG -+ ("ioh_spi_suspend free_irq invoked successfully\n"); -+ IOH_DEBUG -+ ("ioh_spi_suspend pCtrlData->bIrqRegistered\ -+ = false\n"); -+ } -+ -+ /*save config space */ -+ iRetVal = pci_save_state(pDev); -+ -+ if (iRetVal == 0) { -+ IOH_DEBUG -+ ("ioh_spi_suspend pci_save_state returned=%d\n", -+ iRetVal); -+ /*disable PM notifications */ -+ pci_enable_wake(pDev, PCI_D3hot, 0); -+ IOH_DEBUG -+ ("ioh_spi_suspend pci_enable_wake invoked\ -+ successfully\n"); -+ /*disable PCI device */ -+ pci_disable_device(pDev); -+ IOH_DEBUG -+ ("ioh_spi_suspend pci_disable_device invoked\ -+ successfully\n"); -+ /*move device to D3hot state */ -+ pci_set_power_state(pDev, PCI_D3hot); -+ IOH_DEBUG -+ ("ioh_spi_suspend pci_set_power_state invoked\ -+ successfully\n"); -+ } else { -+ IOH_LOG(KERN_ERR, -+ "ioh_spi_suspend pci_save_state failed\n"); -+ } -+ } -+ -+ IOH_DEBUG("ioh_spi_suspend return=%d\n", iRetVal); -+ -+ return iRetVal; -+} -+ -+#endif -+/*! @ingroup SPI_PCILayerAPI -+ -+@fn ioh_spi_resume(struct pci_dev *pDev) -+ -+@brief Implements the resume routine for IOH SPI driver -+ -+@remarks Implements the resume routine for IOH SPI driver -+ -+ The major tasks performed by this method are: -+ - Move the device to D0 power state. -+ - Restore the saved state. -+ - Enable the PCI device. -+ - Disable PM notifications. -+ - Register interrupt handler. -+ - Reset IOH SPI hardware. -+ - Set IOH SPI hardware in master mode. -+ -+@note This function is invoked by the kernel when the system is being -+ resumed from suspend. -+ -+@param pDev [@ref INOUT] contains reference to struct pci_dev -+ -+@retval int -+ - @ref IOH_SPI_SUCCESS The function returns successfully -+ - -EINVAL request_irq fails -+ - -ENOMEM request_irq fails -+ - -ENOSYS request_irq fails -+ - -EBUSY request_irq fails -+ - -EIO pci_enable_device fails -+ -+@see ioh_spi_pcidev -+ -+<hr> -+ -+*/ -+#ifdef CONFIG_PM -+static int ioh_spi_resume(struct pci_dev *pDev) -+{ -+ int i; -+ s32 iRetVal = IOH_SPI_SUCCESS; -+ -+ struct ioh_spi_board_data *pBoardData = pci_get_drvdata(pDev); -+ IOH_DEBUG("ioh_spi_resume ENTRY\n"); -+ -+ if (pBoardData == NULL) { -+ IOH_LOG(KERN_ERR, -+ "ioh_spi_resume pci_get_drvdata returned NULL\n"); -+ iRetVal = -EFAULT; -+ } else { -+ /*move device to DO power state */ -+ pci_set_power_state(pDev, PCI_D0); -+ IOH_DEBUG -+ ("ioh_spi_resume pci_set_power_state invoked successfully\n"); -+ -+ /*restore state */ -+ pci_restore_state(pDev); -+ IOH_DEBUG -+ ("ioh_spi_resume pci_restore_state invoked successfully\n"); -+ iRetVal = pci_enable_device(pDev); -+ if (iRetVal < 0) { -+ IOH_LOG(KERN_ERR, -+ "ioh_spi_resume pci_enable_device failed\n"); -+ } else { -+ IOH_DEBUG -+ ("ioh_spi_resume pci_enable_device returned=%d\n", -+ iRetVal); -+ -+ /*disable PM notifications */ -+ pci_enable_wake(pDev, PCI_D3hot, 0); -+ IOH_DEBUG -+ ("ioh_spi_resume pci_enable_wake invoked\ -+ successfully\n"); -+ -+ /*register IRQ handler */ -+ -+ if ((pBoardData->bIrqRegistered) != true) { -+ /*register IRQ */ -+ iRetVal = request_irq(pBoardData->pDev->irq, -+ ioh_spi_handler, IRQF_SHARED, -+ DRIVER_NAME, -+ pBoardData); -+ if (iRetVal < 0) { -+ IOH_LOG(KERN_ERR, -+ "ioh_spi_resume\ -+ request_irq failed\n"); -+ } else { -+ IOH_DEBUG -+ ("ioh_spi_resume request_irq\ -+ returned=%d\n", -+ iRetVal); -+ pBoardData->bIrqRegistered = true; -+ -+ /*reset IOH SPI h/w */ -+ -+ for (i = 0; i < IOH_SPI_MAX_DEV; i++) { -+ ioh_spi_reset(pBoardData-> -+ pCtrlData[i]-> -+ pMaster); -+ IOH_DEBUG -+ ("ioh_spi_resume\ -+ ioh_spi_reset invoked " -+ "successfully \n"); -+ ioh_spi_set_master_mode -+ (pBoardData->pCtrlData[i]-> -+ pMaster); -+ IOH_DEBUG -+ ("ioh_spi_resume\ -+ ioh_spi_set_master_mode invoked" -+ "successfully \n"); -+ } -+ -+ /*set suspend status to false */ -+ pBoardData->bSuspended = false; -+ -+ IOH_DEBUG -+ ("ioh_spi_resume set pBoardData->\ -+ bSuspending = false\n"); -+ } -+ } -+ } -+ } -+ -+ IOH_DEBUG("ioh_spi_resume returning=%d\n", iRetVal); -+ -+ return iRetVal; -+} -+ -+#endif -+/*! @ingroup SPI_PCILayerFacilitators -+ -+@struct ioh_spi_pcidev_id -+ -+@brief Store information of supported PCI devices -+ -+@see ioh_spi_pcidev -+ -+<hr> -+ -+*/ -+ -+static struct pci_device_id ioh_spi_pcidev_id[] = { -+ /*LSI*/ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_IOH_SPI)}, -+ {0,} -+ -+}; -+ -+/*! @ingroup SPI_PCILayerFacilitators -+ -+@struct ioh_spi_pcidev -+ -+@brief Store the references of PCI driver interfaces to kernel -+ -+@note This structure is registerd with the kernel via the call -+ pci_register_driver from @ref ioh_spi_init -+ -+@see -+ - ioh_spi_init -+ - ioh_spi_exit -+ -+<hr> -+ -+*/ -+ -+static struct pci_driver ioh_spi_pcidev = { -+ .name = "ioh_spi", -+ .id_table = ioh_spi_pcidev_id, -+ .probe = ioh_spi_probe, -+ .remove = ioh_spi_remove, -+#ifdef CONFIG_PM -+ .suspend = ioh_spi_suspend, -+ .resume = ioh_spi_resume, -+#endif -+ -+}; -+ -+/*! @ingroup SPI_InterfaceLayerAPI -+ -+@fn ioh_spi_init(void) -+ -+@brief Entry point function for this module. -+ -+@remarks Init function for IOH SPI driver module -+ -+@param None -+ -+@retval int -+ - 0 Function exits successfully -+ - -EEXIST pci_register_driver fails -+ - -EINVAL pci_register_driver fails -+ - -ENOMEM pci_register_driver fails -+ -+<hr> -+ -+*/ -+static int __init ioh_spi_init(void) -+{ -+ s32 iRetVal; -+ -+ iRetVal = pci_register_driver(&ioh_spi_pcidev); -+ if (iRetVal == 0) { -+ IOH_DEBUG -+ ("ioh_spi_init pci_register_driver invoked successfully\n"); -+ } else { -+ IOH_LOG(KERN_ERR, "ioh_spi_init pci_register_driver failed\n"); -+ } -+ -+ IOH_DEBUG("ioh_spi_init returning=%d\n", iRetVal); -+ -+ return iRetVal; -+} -+ -+/*! @ingroup SPI_InterfaceLayerAPI -+ -+@fn ioh_spi_exit(void) -+ -+@brief Exit point function for this module. -+ -+@remarks Function invoked when module is removed -+ -+@param None -+ -+@retval None -+ -+<hr> -+ -+*/ -+static void __exit ioh_spi_exit(void) -+{ -+ IOH_DEBUG("ioh_spi_exit Invoking pci_unregister_driver\n"); -+ pci_unregister_driver(&ioh_spi_pcidev); -+} -+ -+MODULE_DESCRIPTION("IOH SPI PCI Driver"); -+MODULE_LICENSE("GPL"); -+module_init(ioh_spi_init); -+module_exit(ioh_spi_exit); -diff -urN linux-2.6.33-rc3/drivers/spi/pch_spi_platform_devices.c topcliff-2.6.33-rc3/drivers/spi/pch_spi_platform_devices.c ---- linux-2.6.33-rc3/drivers/spi/pch_spi_platform_devices.c 1970-01-01 09:00:00.000000000 +0900 -+++ topcliff-2.6.33-rc3/drivers/spi/pch_spi_platform_devices.c 2010-03-06 07:44:02.000000000 +0900 -@@ -0,0 +1,50 @@ -+#include <linux/module.h> -+#include <linux/spi/spidev.h> -+#include <linux/device.h> -+#include <linux/spi/spi.h> -+ -+static struct spi_board_info ioh_spi_slaves[] = { -+ { -+ .modalias = "spidev", /* Name of spi_driver for this device*/ -+ .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ*/ -+ .bus_num = 0, /* Framework bus number*/ -+ .chip_select = 0, /* Framework chip select.*/ -+ .platform_data = NULL, -+ .mode = SPI_MODE_0, -+ }, -+#if (CONFIG_PCH_SPI_PLATFORM_DEVICE_COUNT - 1) -+ { -+ .modalias = "spidev", /* Name of spi_driver for this device*/ -+ .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ*/ -+ .bus_num = 1, /* Framework bus number*/ -+ .chip_select = 0, /* Framework chip select.*/ -+ .platform_data = NULL, -+ .mode = SPI_MODE_0, -+ }, -+#endif -+}; -+ -+static __init int Load(void) -+{ -+ int iRetVal = -1; -+ -+ printk(KERN_INFO "Registering IOH SPI devices... \n"); -+ -+ if (!spi_register_board_info -+ (ioh_spi_slaves, ARRAY_SIZE(ioh_spi_slaves))) -+ iRetVal = 0; -+ else -+ printk(KERN_ERR "Registering IOH SPI devices failed\n"); -+ -+ return iRetVal; -+} -+ -+/* -+ * static __exit void Unload() -+ * { -+ * -+ * } -+ * */ -+ -+module_init(Load); -+MODULE_LICENSE("GPL"); |