mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
cb6442aa26
Including the following patches: commit 0f7723bb09440ae69743fed38cf558a838aa9bdf Author: Bryan Huntsman <bryanh@codeaurora.org> Date: Thu Oct 6 23:13:56 2011 -0700 Revert "spi_qsd: GPIO configuration changes for SPI chip-select line" This reverts commit 7eaa08b75995289a91c7dd1f3616f79227f5f923. Signed-off-by: Bryan Huntsman <bryanh@codeaurora.org> commit 7eaa08b75995289a91c7dd1f3616f79227f5f923 Author: Harini Jayaraman <harinij@codeaurora.org> Date: Wed Sep 28 16:26:39 2011 -0600 spi_qsd: GPIO configuration changes for SPI chip-select line The chip-select GPIO's pertaining to each slave remains in suspended configuration until the first transfer is intiated by the slave. Change-Id: I3aa8555289be7ce457b91a969cf03909be0965d7 Signed-off-by: Harini Jayaraman <harinij@codeaurora.org> commit e47df9f9b932968152ab2908153e60adab4402d7 Author: Jordan Crouse <jcrouse@codeaurora.org> Date: Mon Sep 19 11:21:16 2011 -0600 spi_qsd: Fix possible uninitialized variable Change-Id: Ic0dedbad184046e9835cde015ad5d592f33e82a6 Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org> commit 4ae02c76b98f2b96bfb8c4fa02f40cfda2f16f97 Author: Harini Jayaraman <harinij@codeaurora.org> Date: Tue Sep 20 17:28:50 2011 -0600 spi_qsd: Fix Klocwork errors in SPI driver Change-Id: I1fe6632e68ea625966aced37a1b140b30534e101 Signed-off-by: Harini Jayaraman <harinij@codeaurora.org> commit 52e065ba3d86977b59937693ac7e85836cf4eca8 Author: Harini Jayaraman <harinij@codeaurora.org> Date: Thu Sep 1 12:12:58 2011 -0600 spi_qsd: Fix for SPI Operational State Invalid error This error is reproted randomly when the SPI core is put into RUN state and occurs when the ACPU clock is low. When the timer expires, we check again to ensure that the STATE_VALID bit is set before returning. Change-Id: Ic8912534f4924efd999b8aa1d75a9fd19749e870 CRs-fixed: 304672 Signed-off-by: Harini Jayaraman <harinij@codeaurora.org> commit a9a8816913e5466e06b443c42cbf8ae866b95fd1 Author: Jeff Ohlstein <johlstei@codeaurora.org> Date: Fri Sep 2 13:55:16 2011 -0700 msm: dma: remove crci conflict checking The crci conflict checking code was designed for a system where a crci's mux could be changed at runtime. In reality, our chips configure these statically, so it is not necessary. Change-Id: I4d5f32cd8728d3c78fca8f64aed0e02b57b6afba Signed-off-by: Jeff Ohlstein <johlstei@codeaurora.org> commit 36c6f1bb48af3e65db281cc7ccb913a8e81a598e Author: Matt Wagantall <mattw@codeaurora.org> Date: Wed Aug 17 15:44:58 2011 -0700 msm: clock: Rename all I2C/SPI clocks to 'core_clk' or "iface_clk" Drivers should now use their device names to distinguish between clocks of the same type rather than the clock name. Change-Id: Iab12caf4eab163773d68f1b2adc1bb4c72c69e83 Signed-off-by: Matt Wagantall <mattw@codeaurora.org> commit 55e656e68cac78eaa367341df2e693a483a53f84 Author: Stepan Moskovchenko <stepanm@codeaurora.org> Date: Mon Jun 6 14:34:38 2011 -0700 drivers: barriers: Replace dsb() with mb() Replace explicit dsb() calls with mb(). Now that the generic ARM implementation defines mb() to mean (at least) dsb(), it is appropriate to switch back to the generic kernel version of the barriers. This is also needed for correctness on certain targets (such as 7x27) where dsb() is insufficient and other operations (such as outer cache sync or writing to strongly-ordered memory) are required to ensure proper I/O operations ordering. In some cases, remove explicit calls to outer_sync following a barrier since the barrier will now have an explicit outer_sync call. Change-Id: I2c53b8534af9c3cbac4d4d77b322f897a39e7758 Signed-off-by: Stepan Moskovchenko <stepanm@codeaurora.org> commit 17194a32164b868f80ce84e313f9148d1dc77e7b Author: Harini Jayaraman <harinij@codeaurora.org> Date: Fri Jun 3 18:10:09 2011 -0600 spi_qsd: GPIO configuration changes On suspend, the SPI related GPIO's enter a low power configuration and on resume they move to an active configuration. This helps conserving power during power collapse. Change-Id: I0911867e10fadcfc6950f6dddf74226bd6321c16 Signed-off-by: Harini Jayaraman <harinij@codeaurora.org> commit 1777d88688511cd59bad7674c6a2246e0c93142b Author: Harini Jayaraman <harinij@codeaurora.org> Date: Wed Jun 1 16:54:07 2011 -0600 spi_qsd: Remove restriction on SPI clock speed. When multiple slaves are connected to the SPI controller, the driver does not allow the clock to go from lower speed to a higher speed. This restriction is not required since there can only be one slave listening at a time. Also, there are no hardware limitations in doing so. Change-Id: I4ecabfb3a1515416f050c18678cf0987dcde9d1e CRs-fixed: 290127 Signed-off-by: Harini Jayaraman <harinij@codeaurora.org> commit 4b7c7bfc546cb02141da9d034421aefe5635f857 Author: Harini Jayaraman <harinij@codeaurora.org> Date: Tue Jun 7 14:18:42 2011 -0600 spi_qsd: Add null pointer check before dereferencing During probe, there is no cur_msg to set the status. Change-Id: I82e00b9d74d45c36b70078b171db1bb150d1bfac Signed-off-by: Harini Jayaraman <harinij@codeaurora.org> commit bf514c766fcc2bdee680f80a2ea16c7fead0be96 Author: Stepan Moskovchenko <stepanm@codeaurora.org> Date: Mon May 16 13:37:11 2011 -0700 msm: spi: Fix access to unclocked registers Don't program the GSBI configuration until the clocks have been turned on. Change-Id: Idee5f5dffcb5ed0f7de18f1e508ee8c76b618894 Signed-off-by: Stepan Moskovchenko <stepanm@codeaurora.org> commit d9c248213f4cd025f3d3586f0de81e4bc44a5a54 Author: Harini Jayaraman <harinij@codeaurora.org> Date: Mon May 16 16:43:08 2011 -0600 spi_qsd: Fix for SPI input overrun error This error occurs due to a bug in the controller. This bogus error is reported when a transition from run to reset state occurs and if the input FIFO has an odd number of entries. Change-Id: I555864d4855ac6d416997da69d8bc6aee7a82178 Signed-off-by: Harini Jayaraman <harinij@codeaurora.org> commit e99ceb5b3da7bec51be853809c25df8e32b2c1e6 Author: Harini Jayaraman <harinij@codeaurora.org> Date: Thu Apr 14 18:36:34 2011 -0600 spi_qsd: Multi-transfer handling When there are mulitple SPI transfers in a message, we default to using FIFO mode for all the transfers. As special case, we handle a WR-WR or WR-RD transfer where we choose between FIFO mode and DM mode based on the total length of the transaction. Change-Id: I6fbc1a06a22f9782db5b97c9b87cc53392a8c2fa CRs-fixed: 276666 Signed-off-by: Harini Jayaraman <harinij@codeaurora.org> commit 8f3d3aaa51603a929027bc820fe2d3515e959779 Author: Harini Jayaraman <harinij@codeaurora.org> Date: Tue Apr 19 14:19:29 2011 -0600 spi_qsd: Ensure IO operation ordering Adding memory barriers to ensure that the writes and reads to the SPI and QUP registers happen in the correct order. Change-Id: I86d8f63b0e9547a2339ee4ab5c713cf8864fef04 Signed-off-by: Harini Jayaraman <harinij@codeaurora.org> commit 36b3fae5f54230cd1e4ca072d1f55cb2f79d8945 Author: Laura Abbott <lauraa@codeaurora.org> Date: Thu Oct 14 12:48:16 2010 -0700 spi_qsd: Fix section mismatch The function msm_spi_probe is referenced outside of the __init section. This fixes the problem by calling platform_driver_probe instead of platform_driver_register since this device is not hotplugable. Change-Id: I3a563c6fc562ada959317b54ff60a38f9ce517d8 Signed-off-by: Laura Abbott <lauraa@codeaurora.org> commit dc2e36eecefb6628031afeff28afd9d97f2f3f6f Author: Harini Jayaraman <harinij@codeaurora.org> Date: Wed Sep 29 16:58:20 2010 -0600 spi_qsd: Changes to support DM mode. The dma_config function may not always be present. This change makes sure the driver gets DM resources irrespective of the dma_config function. Change-Id: I25a2497d20e973f22b76f2b5d6f68c86bd4d5f1d Signed-off-by: Harini Jayaraman <harinij@codeaurora.org> commit a39bd4a398674c320925540eec91d94d2b7d53f3 Author: Harini Jayaraman <harinij@codeaurora.org> Date: Thu Aug 19 17:48:01 2010 -0600 spi_qsd: Modify timeout mechanism to check SPI state valid bit. In order to allow sufficient time for the SPI state transition to occur, calculate the timeout based on the SPI clock speed. Change-Id: I3d6955b2a64a8bf8980590e352fbd564250210fb CRs-fixed: 250998 Signed-off-by: Harini Jayaraman <harinij@codeaurora.org> commit b5887b644ba9545672d637985713c7e0e2e5bb50 Author: Harini Jayaraman <harinij@codeaurora.org> Date: Tue Aug 3 16:57:33 2010 -0600 spi_qsd: Use FIFO mode when DM mode configuration fails. When the Data Mover configuration fails, the driver uses FIFO mode. Change-Id: Iaf83e50fe725654c58260c5cd1150cdeb56f51c8 CRs-fixed: 249238 Signed-off-by: Harini Jayaraman <harinij@codeaurora.org> commit ced8ad320d480006643a3aa3474f5c0d77457454 Author: Harini Jayaraman <harinij@codeaurora.org> Date: Mon Jun 28 16:01:33 2010 -0600 spi_qsd: Use SW timeout instead of SPI_TIME_OUT register. Since the software timeout is already present in the driver, the hardware SPI_TIME_OUT register is being removed.It is just redundant and used only for debugging purposes. Change-Id: I829cb944444fc3e5053bc810adffe2b87f511b63 Signed-off-by: Harini Jayaraman <harinij@codeaurora.org> commit 35e9155f59317e8ef63b8ce5190f26f5cae6a8ee Author: Harini Jayaraman <harinij@codeaurora.org> Date: Fri Jun 25 16:48:25 2010 -0600 spi_qsd: Disable irqs in the probe function. The irqs are disabled at all times in the probe function irrespective of the use of remote lock. Change-Id: I0997d07b93c97a12bca6d80a9bba59682b1bec3e Signed-off-by: Harini Jayaraman <harinij@codeaurora.org> commit e6af92d74a35ba267125bc61c2c6c18034c03af3 Author: Harini Jayaraman <harinij@codeaurora.org> Date: Tue Jun 22 12:20:46 2010 -0600 spi_qsd: Disable clocks and irqs when SPI bus is not in use. The SPI clocks and irqs are enabled per workqueue and correspondingly disabled once the workqueue is completed. Change-Id: Ib22b7e3b946eb4c829940e43327caaf5aff7721b CRs-fixed: 242866 Signed-off-by: Harini Jayaraman <harinij@codeaurora.org> commit b25e4220efdacc231cb150fc263af1e3f525b165 Author: Lena Salman <esalman@qualcomm.com> Date: Tue Jun 8 15:25:47 2010 +0300 spi_qsd: Add usage of MX_WRITE_COUNT register Use MX_WRITE_COUNT register to reduce the amount of TX interrupts in FIFO mode for transfers smaller than FIFO size. Change-Id: I7208fdc85b626a31a8b781ee5c56f73beee6c427 Signed-off-by: Lena Salman <esalman@qualcomm.com> commit 7ed56f3441c5ebe7fd8107fb8468207a88bc743f Author: Lena Salman <esalman@qualcomm.com> Date: Wed Jun 9 16:14:44 2010 +0300 spi_qsd: Minor changes to support Data Mover mode on QUPe core Minor changes to support Data Mover made on QUPe core. Change-Id: I54663115a43f7fd9b52a2ddee796b5499d5f239a Signed-off-by: Lena Salman <esalman@qualcomm.com> commit a85fd0ab6484eb2ef404c062adffce1ee22337f1 Author: Lena Salman <esalman@qualcomm.com> Date: Thu Jun 3 13:57:02 2010 +0300 spi_qsd: Add support for QUPe controller QUPe controller is a new version of Qualcomm SPI controller. The controller also supports other peripheral protocols, however its SPI functionality is very similar to previous SPI core, supported by spi_qsd. Therefore the same driver is being utilized with some register address modification and minor flow change. Change-Id: Ic091ef2c2ed699b43f786c278b613e69a7e9039b Signed-off-by: Lena Salman <esalman@qualcomm.com> commit ce270f6f9198cf40ee5638b35e595da81116241e Author: Jeff Ohlstein <johlstei@quicinc.com> Date: Thu Apr 29 13:40:53 2010 -0700 drivers: spi: Support ADM3 in spi_qsd driver Change-Id: I6dfa38a4c33a8e4619d56ce30787e1aeafc8356d Signed-off-by: Jeff Ohlstein <johlstei@quicinc.com> commit 47346fa611773ef92d12d9145ea33a7f2c79052f Author: Lena Salman <esalman@qualcomm.com> Date: Wed Apr 28 11:33:15 2010 +0300 spi_qsd: Add disable/enable of pclk to suspend/resume functions Add disable/enable of pclk to suspend/resume functions to improve power performance. Change-Id: I871e5ac90a998f2942778bb1e8c2c9d583a9ae00 CRs-fixed: 235046 Signed-off-by: Lena Salman <esalman@qualcomm.com> commit a96eba98fbbd21ac657f5d551466909352766ead Author: Lena Salman <esalman@qualcomm.com> Date: Sun Apr 11 10:40:37 2010 +0300 spi_qsd: Making irq code implicit for the core mode in use Make code clear regarding what mode is in use in the irq. Signed-off-by: Lena Salman <esalman@qualcomm.com> commit 6a02d85f8f48cf6f86cddc38c9fce9c1179208b4 Author: Lena Salman <esalman@qualcomm.com> Date: Tue Apr 13 21:16:45 2010 +0300 spi_qsd: Separate tx/rx/error statistics between contexts To improve SMP safety, separate the tx/error statistics between contexts. This protects the statistics from accidentally being access from another context at the same time. Change-Id: Ibc52406e7b06a4bb5142f8a09a2f35442cb9df8a Signed-off-by: Lena Salman <esalman@qualcomm.com> commit 31f301c171aab8e42f8b6abe9b7866412cb546a8 Author: Lena Salman <esalman@qualcomm.com> Date: Tue Mar 23 14:51:00 2010 +0200 spi_qsd: Add better handling for pending transfers during suspend To improve SMP safety, add better handling in suspend function to wait for graceful closure of pending transfers. This graceful closure waits for all the pending transfers to finish or timeout, while not allowing new ones to queue up. This allows correct handling of all the resources involved in a transfer before suspend. Signed-off-by: Lena Salman <esalman@qualcomm.com> commit 8fbf6e4c5371520b5f9de2001e2ebd15773e918b Author: Lena Salman <esalman@qualcomm.com> Date: Thu Mar 25 10:44:10 2010 +0200 spi_qsd: Add mutex to get exclusive access to controller registers To improve SMP safety, add mutex to get exclusive access to controller registers. Signed-off-by: Lena Salman <esalman@qualcomm.com> commit 9405adda67d8c6a856243e599f09d806b4bc6de5 Author: Kenneth Heitke <kheitke@quicinc.com> Date: Thu Apr 15 16:33:16 2010 -0600 spi_qsd: Move global input_fifo_size to device context. Fix reference to device data input_fifo_size which is missing from the previous patch. Change-Id: Ia469896edd0fd90d7ded2b8ec44f9075474b3ec8 Signed-off-by: Kenneth Heitke <kheitke@quicinc.com> commit 6031094ca6a940a47437bc6a092e813b4bc41d2a Author: Lena Salman <esalman@qualcomm.com> Date: Sun Apr 11 10:34:48 2010 +0300 spi_qsd: Move global input_fifo_size to device context. To improve SMP safety move global variable input_fifo_size to device context. Signed-off-by: Lena Salman <esalman@qualcomm.com> commit 97f585033413b1f8ae210bbffd617a4af3462982 Author: Lena Salman <esalman@qualcomm.com> Date: Wed Apr 14 18:35:54 2010 +0300 spi_qsd: Initial contribution of the MSM SPI driver This adds MSM SPI controller driver. The driver is SPI master, and allows slave connections. Current version of the driver supports FIFO and DM modes chosen upon the message size. The driver also supports loopback mode which can be used for testing purposes. This is a squashed version of all the MSM SPI driver changes on the QuIC MSM 2.6.29 kernel which can be found at www.codeaurora.org. It also contains all relevant adaptations to SPI core changes in 2.6.32 kernel. https://www.codeaurora.org/gitweb/quic/la/?p=kernel/msm.git;a=blob;f=drivers/spi/spi_qsd.c;h=1c8e3ec727b29040648ef9a4949396f7109528ae;hb=refs/heads/android-msm-2.6.29b Change-Id: Ibc1e71deb662af87deed77f10dcc8a3a46a8f012 Signed-off-by: Lena Salman <esalman@qualcomm.com> Signed-off-by: David Brown <davidb@codeaurora.org>
493 lines
17 KiB
C
493 lines
17 KiB
C
/* Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 and
|
|
* only version 2 as published by the Free Software Foundation.
|
|
*
|
|
* 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.
|
|
*
|
|
*/
|
|
|
|
#ifndef _SPI_QSD_H
|
|
#define _SPI_QSD_H
|
|
|
|
#define SPI_DRV_NAME "spi_qsd"
|
|
|
|
#if defined(CONFIG_SPI_QSD) || defined(CONFIG_SPI_QSD_MODULE)
|
|
|
|
#define QSD_REG(x) (x)
|
|
#define QUP_REG(x)
|
|
|
|
#define SPI_FIFO_WORD_CNT 0x0048
|
|
|
|
#else
|
|
|
|
#define QSD_REG(x)
|
|
#define QUP_REG(x) (x)
|
|
|
|
#define QUP_CONFIG 0x0000 /* N & NO_INPUT/NO_OUPUT bits */
|
|
#define QUP_ERROR_FLAGS_EN 0x030C
|
|
#define QUP_ERR_MASK 0x3
|
|
#define SPI_OUTPUT_FIFO_WORD_CNT 0x010C
|
|
#define SPI_INPUT_FIFO_WORD_CNT 0x0214
|
|
#define QUP_MX_WRITE_COUNT 0x0150
|
|
#define QUP_MX_WRITE_CNT_CURRENT 0x0154
|
|
|
|
#define QUP_CONFIG_SPI_MODE 0x0100
|
|
#endif
|
|
|
|
#define GSBI_CTRL_REG 0x0
|
|
#define GSBI_SPI_CONFIG 0x30
|
|
#define QUP_HARDWARE_VER 0x0030
|
|
#define QUP_OPERATIONAL_MASK 0x0028
|
|
#define QUP_ERROR_FLAGS 0x0308
|
|
|
|
#define SPI_CONFIG QSD_REG(0x0000) QUP_REG(0x0300)
|
|
#define SPI_IO_CONTROL QSD_REG(0x0004) QUP_REG(0x0304)
|
|
#define SPI_IO_MODES QSD_REG(0x0008) QUP_REG(0x0008)
|
|
#define SPI_SW_RESET QSD_REG(0x000C) QUP_REG(0x000C)
|
|
#define SPI_TIME_OUT_CURRENT QSD_REG(0x0014) QUP_REG(0x0014)
|
|
#define SPI_MX_OUTPUT_COUNT QSD_REG(0x0018) QUP_REG(0x0100)
|
|
#define SPI_MX_OUTPUT_CNT_CURRENT QSD_REG(0x001C) QUP_REG(0x0104)
|
|
#define SPI_MX_INPUT_COUNT QSD_REG(0x0020) QUP_REG(0x0200)
|
|
#define SPI_MX_INPUT_CNT_CURRENT QSD_REG(0x0024) QUP_REG(0x0204)
|
|
#define SPI_MX_READ_COUNT QSD_REG(0x0028) QUP_REG(0x0208)
|
|
#define SPI_MX_READ_CNT_CURRENT QSD_REG(0x002C) QUP_REG(0x020C)
|
|
#define SPI_OPERATIONAL QSD_REG(0x0030) QUP_REG(0x0018)
|
|
#define SPI_ERROR_FLAGS QSD_REG(0x0034) QUP_REG(0x001C)
|
|
#define SPI_ERROR_FLAGS_EN QSD_REG(0x0038) QUP_REG(0x0020)
|
|
#define SPI_DEASSERT_WAIT QSD_REG(0x003C) QUP_REG(0x0310)
|
|
#define SPI_OUTPUT_DEBUG QSD_REG(0x0040) QUP_REG(0x0108)
|
|
#define SPI_INPUT_DEBUG QSD_REG(0x0044) QUP_REG(0x0210)
|
|
#define SPI_TEST_CTRL QSD_REG(0x004C) QUP_REG(0x0024)
|
|
#define SPI_OUTPUT_FIFO QSD_REG(0x0100) QUP_REG(0x0110)
|
|
#define SPI_INPUT_FIFO QSD_REG(0x0200) QUP_REG(0x0218)
|
|
#define SPI_STATE QSD_REG(SPI_OPERATIONAL) QUP_REG(0x0004)
|
|
|
|
/* SPI_CONFIG fields */
|
|
#define SPI_CFG_INPUT_FIRST 0x00000200
|
|
#define SPI_NO_INPUT 0x00000080
|
|
#define SPI_NO_OUTPUT 0x00000040
|
|
#define SPI_CFG_LOOPBACK 0x00000100
|
|
#define SPI_CFG_N 0x0000001F
|
|
|
|
/* SPI_IO_CONTROL fields */
|
|
#define SPI_IO_C_FORCE_CS 0x00000800
|
|
#define SPI_IO_C_CLK_IDLE_HIGH 0x00000400
|
|
#define SPI_IO_C_MX_CS_MODE 0x00000100
|
|
#define SPI_IO_C_CS_N_POLARITY 0x000000F0
|
|
#define SPI_IO_C_CS_N_POLARITY_0 0x00000010
|
|
#define SPI_IO_C_CS_SELECT 0x0000000C
|
|
#define SPI_IO_C_TRISTATE_CS 0x00000002
|
|
#define SPI_IO_C_NO_TRI_STATE 0x00000001
|
|
|
|
/* SPI_IO_MODES fields */
|
|
#define SPI_IO_M_OUTPUT_BIT_SHIFT_EN QSD_REG(0x00004000) QUP_REG(0x00010000)
|
|
#define SPI_IO_M_PACK_EN QSD_REG(0x00002000) QUP_REG(0x00008000)
|
|
#define SPI_IO_M_UNPACK_EN QSD_REG(0x00001000) QUP_REG(0x00004000)
|
|
#define SPI_IO_M_INPUT_MODE QSD_REG(0x00000C00) QUP_REG(0x00003000)
|
|
#define SPI_IO_M_OUTPUT_MODE QSD_REG(0x00000300) QUP_REG(0x00000C00)
|
|
#define SPI_IO_M_INPUT_FIFO_SIZE QSD_REG(0x000000C0) QUP_REG(0x00000380)
|
|
#define SPI_IO_M_INPUT_BLOCK_SIZE QSD_REG(0x00000030) QUP_REG(0x00000060)
|
|
#define SPI_IO_M_OUTPUT_FIFO_SIZE QSD_REG(0x0000000C) QUP_REG(0x0000001C)
|
|
#define SPI_IO_M_OUTPUT_BLOCK_SIZE QSD_REG(0x00000003) QUP_REG(0x00000003)
|
|
|
|
#define INPUT_BLOCK_SZ_SHIFT QSD_REG(4) QUP_REG(5)
|
|
#define INPUT_FIFO_SZ_SHIFT QSD_REG(6) QUP_REG(7)
|
|
#define OUTPUT_BLOCK_SZ_SHIFT QSD_REG(0) QUP_REG(0)
|
|
#define OUTPUT_FIFO_SZ_SHIFT QSD_REG(2) QUP_REG(2)
|
|
#define OUTPUT_MODE_SHIFT QSD_REG(8) QUP_REG(10)
|
|
#define INPUT_MODE_SHIFT QSD_REG(10) QUP_REG(12)
|
|
|
|
/* SPI_OPERATIONAL fields */
|
|
#define SPI_OP_MAX_INPUT_DONE_FLAG 0x00000800
|
|
#define SPI_OP_MAX_OUTPUT_DONE_FLAG 0x00000400
|
|
#define SPI_OP_INPUT_SERVICE_FLAG 0x00000200
|
|
#define SPI_OP_OUTPUT_SERVICE_FLAG 0x00000100
|
|
#define SPI_OP_INPUT_FIFO_FULL 0x00000080
|
|
#define SPI_OP_OUTPUT_FIFO_FULL 0x00000040
|
|
#define SPI_OP_IP_FIFO_NOT_EMPTY 0x00000020
|
|
#define SPI_OP_OP_FIFO_NOT_EMPTY 0x00000010
|
|
#define SPI_OP_STATE_VALID 0x00000004
|
|
#define SPI_OP_STATE 0x00000003
|
|
|
|
#define SPI_OP_STATE_CLEAR_BITS 0x2
|
|
enum msm_spi_state {
|
|
SPI_OP_STATE_RESET = 0x00000000,
|
|
SPI_OP_STATE_RUN = 0x00000001,
|
|
SPI_OP_STATE_PAUSE = 0x00000003,
|
|
};
|
|
|
|
/* SPI_ERROR_FLAGS fields */
|
|
#define SPI_ERR_OUTPUT_OVER_RUN_ERR 0x00000020
|
|
#define SPI_ERR_INPUT_UNDER_RUN_ERR 0x00000010
|
|
#define SPI_ERR_OUTPUT_UNDER_RUN_ERR 0x00000008
|
|
#define SPI_ERR_INPUT_OVER_RUN_ERR 0x00000004
|
|
#define SPI_ERR_CLK_OVER_RUN_ERR 0x00000002
|
|
#define SPI_ERR_CLK_UNDER_RUN_ERR 0x00000001
|
|
|
|
/* We don't allow transactions larger than 4K-64 or 64K-64 due to
|
|
mx_input/output_cnt register size */
|
|
#define SPI_MAX_TRANSFERS QSD_REG(0xFC0) QUP_REG(0xFC0)
|
|
#define SPI_MAX_LEN (SPI_MAX_TRANSFERS * dd->bytes_per_word)
|
|
|
|
#define SPI_NUM_CHIPSELECTS 4
|
|
#define SPI_SUPPORTED_MODES (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP)
|
|
|
|
#define SPI_DELAY_THRESHOLD 1
|
|
/* Default timeout is 10 milliseconds */
|
|
#define SPI_DEFAULT_TIMEOUT 10
|
|
/* 250 microseconds */
|
|
#define SPI_TRYLOCK_DELAY 250
|
|
|
|
/* Data Mover burst size */
|
|
#define DM_BURST_SIZE 16
|
|
/* Data Mover commands should be aligned to 64 bit(8 bytes) */
|
|
#define DM_BYTE_ALIGN 8
|
|
|
|
#define SPI_QUP_VERSION_NONE 0x0
|
|
#define SPI_QUP_VERSION_BFAM 0x2
|
|
|
|
static char const * const spi_rsrcs[] = {
|
|
"spi_clk",
|
|
"spi_miso",
|
|
"spi_mosi"
|
|
};
|
|
|
|
static char const * const spi_cs_rsrcs[] = {
|
|
"spi_cs",
|
|
"spi_cs1",
|
|
"spi_cs2",
|
|
"spi_cs3",
|
|
};
|
|
|
|
enum msm_spi_mode {
|
|
SPI_FIFO_MODE = 0x0, /* 00 */
|
|
SPI_BLOCK_MODE = 0x1, /* 01 */
|
|
SPI_DMOV_MODE = 0x2, /* 10 */
|
|
SPI_BAM_MODE = 0x3, /* 11 */
|
|
SPI_MODE_NONE = 0xFF, /* invalid value */
|
|
};
|
|
|
|
/* Structure for SPI CS GPIOs */
|
|
struct spi_cs_gpio {
|
|
int gpio_num;
|
|
bool valid;
|
|
};
|
|
|
|
/* Structures for Data Mover */
|
|
struct spi_dmov_cmd {
|
|
dmov_box box; /* data aligned to max(dm_burst_size, block_size)
|
|
(<= fifo_size) */
|
|
dmov_s single_pad; /* data unaligned to max(dm_burst_size, block_size)
|
|
padded to fit */
|
|
dma_addr_t cmd_ptr;
|
|
};
|
|
|
|
static struct pm_qos_request qos_req_list;
|
|
|
|
#ifdef CONFIG_DEBUG_FS
|
|
/* Used to create debugfs entries */
|
|
static const struct {
|
|
const char *name;
|
|
mode_t mode;
|
|
int offset;
|
|
} debugfs_spi_regs[] = {
|
|
{"config", S_IRUGO | S_IWUSR, SPI_CONFIG},
|
|
{"io_control", S_IRUGO | S_IWUSR, SPI_IO_CONTROL},
|
|
{"io_modes", S_IRUGO | S_IWUSR, SPI_IO_MODES},
|
|
{"sw_reset", S_IWUSR, SPI_SW_RESET},
|
|
{"time_out_current", S_IRUGO, SPI_TIME_OUT_CURRENT},
|
|
{"mx_output_count", S_IRUGO | S_IWUSR, SPI_MX_OUTPUT_COUNT},
|
|
{"mx_output_cnt_current", S_IRUGO, SPI_MX_OUTPUT_CNT_CURRENT},
|
|
{"mx_input_count", S_IRUGO | S_IWUSR, SPI_MX_INPUT_COUNT},
|
|
{"mx_input_cnt_current", S_IRUGO, SPI_MX_INPUT_CNT_CURRENT},
|
|
{"mx_read_count", S_IRUGO | S_IWUSR, SPI_MX_READ_COUNT},
|
|
{"mx_read_cnt_current", S_IRUGO, SPI_MX_READ_CNT_CURRENT},
|
|
{"operational", S_IRUGO | S_IWUSR, SPI_OPERATIONAL},
|
|
{"error_flags", S_IRUGO | S_IWUSR, SPI_ERROR_FLAGS},
|
|
{"error_flags_en", S_IRUGO | S_IWUSR, SPI_ERROR_FLAGS_EN},
|
|
{"deassert_wait", S_IRUGO | S_IWUSR, SPI_DEASSERT_WAIT},
|
|
{"output_debug", S_IRUGO, SPI_OUTPUT_DEBUG},
|
|
{"input_debug", S_IRUGO, SPI_INPUT_DEBUG},
|
|
{"test_ctrl", S_IRUGO | S_IWUSR, SPI_TEST_CTRL},
|
|
{"output_fifo", S_IWUSR, SPI_OUTPUT_FIFO},
|
|
{"input_fifo" , S_IRUSR, SPI_INPUT_FIFO},
|
|
{"spi_state", S_IRUGO | S_IWUSR, SPI_STATE},
|
|
#if defined(CONFIG_SPI_QSD) || defined(CONFIG_SPI_QSD_MODULE)
|
|
{"fifo_word_cnt", S_IRUGO, SPI_FIFO_WORD_CNT},
|
|
#else
|
|
{"qup_config", S_IRUGO | S_IWUSR, QUP_CONFIG},
|
|
{"qup_error_flags", S_IRUGO | S_IWUSR, QUP_ERROR_FLAGS},
|
|
{"qup_error_flags_en", S_IRUGO | S_IWUSR, QUP_ERROR_FLAGS_EN},
|
|
{"mx_write_cnt", S_IRUGO | S_IWUSR, QUP_MX_WRITE_COUNT},
|
|
{"mx_write_cnt_current", S_IRUGO, QUP_MX_WRITE_CNT_CURRENT},
|
|
{"output_fifo_word_cnt", S_IRUGO, SPI_OUTPUT_FIFO_WORD_CNT},
|
|
{"input_fifo_word_cnt", S_IRUGO, SPI_INPUT_FIFO_WORD_CNT},
|
|
#endif
|
|
};
|
|
#endif
|
|
|
|
struct msm_spi {
|
|
u8 *read_buf;
|
|
const u8 *write_buf;
|
|
void __iomem *base;
|
|
struct device *dev;
|
|
spinlock_t queue_lock;
|
|
struct mutex core_lock;
|
|
struct list_head queue;
|
|
struct workqueue_struct *workqueue;
|
|
struct work_struct work_data;
|
|
struct spi_message *cur_msg;
|
|
struct spi_transfer *cur_transfer;
|
|
struct completion transfer_complete;
|
|
struct clk *clk;
|
|
struct clk *pclk;
|
|
unsigned long mem_phys_addr;
|
|
size_t mem_size;
|
|
int input_fifo_size;
|
|
int output_fifo_size;
|
|
u32 rx_bytes_remaining;
|
|
u32 tx_bytes_remaining;
|
|
u32 clock_speed;
|
|
int irq_in;
|
|
int read_xfr_cnt;
|
|
int write_xfr_cnt;
|
|
int write_len;
|
|
int read_len;
|
|
#if defined(CONFIG_SPI_QSD) || defined(CONFIG_SPI_QSD_MODULE)
|
|
int irq_out;
|
|
int irq_err;
|
|
#endif
|
|
int bytes_per_word;
|
|
bool suspended;
|
|
bool transfer_pending;
|
|
wait_queue_head_t continue_suspend;
|
|
/* DMA data */
|
|
enum msm_spi_mode mode;
|
|
bool use_dma;
|
|
int tx_dma_chan;
|
|
int tx_dma_crci;
|
|
int rx_dma_chan;
|
|
int rx_dma_crci;
|
|
/* Data Mover Commands */
|
|
struct spi_dmov_cmd *tx_dmov_cmd;
|
|
struct spi_dmov_cmd *rx_dmov_cmd;
|
|
/* Physical address of the tx dmov box command */
|
|
dma_addr_t tx_dmov_cmd_dma;
|
|
dma_addr_t rx_dmov_cmd_dma;
|
|
struct msm_dmov_cmd tx_hdr;
|
|
struct msm_dmov_cmd rx_hdr;
|
|
int input_block_size;
|
|
int output_block_size;
|
|
int burst_size;
|
|
atomic_t rx_irq_called;
|
|
atomic_t tx_irq_called;
|
|
/* Used to pad messages unaligned to block size */
|
|
u8 *tx_padding;
|
|
dma_addr_t tx_padding_dma;
|
|
u8 *rx_padding;
|
|
dma_addr_t rx_padding_dma;
|
|
u32 unaligned_len;
|
|
/* DMA statistics */
|
|
int stat_dmov_tx_err;
|
|
int stat_dmov_rx_err;
|
|
int stat_rx;
|
|
int stat_dmov_rx;
|
|
int stat_tx;
|
|
int stat_dmov_tx;
|
|
#ifdef CONFIG_DEBUG_FS
|
|
struct dentry *dent_spi;
|
|
struct dentry *debugfs_spi_regs[ARRAY_SIZE(debugfs_spi_regs)];
|
|
#endif
|
|
struct msm_spi_platform_data *pdata; /* Platform data */
|
|
/* Remote Spinlock Data */
|
|
bool use_rlock;
|
|
remote_mutex_t r_lock;
|
|
uint32_t pm_lat;
|
|
/* When set indicates multiple transfers in a single message */
|
|
bool multi_xfr;
|
|
bool done;
|
|
u32 cur_msg_len;
|
|
/* Used in FIFO mode to keep track of the transfer being processed */
|
|
struct spi_transfer *cur_tx_transfer;
|
|
struct spi_transfer *cur_rx_transfer;
|
|
/* Temporary buffer used for WR-WR or WR-RD transfers */
|
|
u8 *temp_buf;
|
|
/* GPIO pin numbers for SPI clk, miso and mosi */
|
|
int spi_gpios[ARRAY_SIZE(spi_rsrcs)];
|
|
/* SPI CS GPIOs for each slave */
|
|
struct spi_cs_gpio cs_gpios[ARRAY_SIZE(spi_cs_rsrcs)];
|
|
int qup_ver;
|
|
};
|
|
|
|
/* Forward declaration */
|
|
static irqreturn_t msm_spi_input_irq(int irq, void *dev_id);
|
|
static irqreturn_t msm_spi_output_irq(int irq, void *dev_id);
|
|
static irqreturn_t msm_spi_error_irq(int irq, void *dev_id);
|
|
static inline int msm_spi_set_state(struct msm_spi *dd,
|
|
enum msm_spi_state state);
|
|
static void msm_spi_write_word_to_fifo(struct msm_spi *dd);
|
|
static inline void msm_spi_write_rmn_to_fifo(struct msm_spi *dd);
|
|
static inline irqreturn_t msm_spi_qup_irq(int irq, void *dev_id);
|
|
|
|
#if defined(CONFIG_SPI_QSD) || defined(CONFIG_SPI_QSD_MODULE)
|
|
static inline void msm_spi_disable_irqs(struct msm_spi *dd)
|
|
{
|
|
disable_irq(dd->irq_in);
|
|
disable_irq(dd->irq_out);
|
|
disable_irq(dd->irq_err);
|
|
}
|
|
|
|
static inline void msm_spi_enable_irqs(struct msm_spi *dd)
|
|
{
|
|
enable_irq(dd->irq_in);
|
|
enable_irq(dd->irq_out);
|
|
enable_irq(dd->irq_err);
|
|
}
|
|
|
|
static inline int msm_spi_request_irq(struct msm_spi *dd,
|
|
struct platform_device *pdev,
|
|
struct spi_master *master)
|
|
{
|
|
int rc;
|
|
|
|
dd->irq_in = platform_get_irq(pdev, 0);
|
|
dd->irq_out = platform_get_irq(pdev, 1);
|
|
dd->irq_err = platform_get_irq(pdev, 2);
|
|
if ((dd->irq_in < 0) || (dd->irq_out < 0) || (dd->irq_err < 0))
|
|
return -EINVAL;
|
|
|
|
rc = devm_request_irq(dd->dev, dd->irq_in, msm_spi_input_irq,
|
|
IRQF_TRIGGER_RISING, pdev->name, dd);
|
|
if (rc)
|
|
goto error_irq;
|
|
|
|
rc = devm_request_irq(dd->dev, dd->irq_out, msm_spi_output_irq,
|
|
IRQF_TRIGGER_RISING, pdev->name, dd);
|
|
if (rc)
|
|
goto error_irq;
|
|
|
|
rc = devm_request_irq(dd->dev, dd->irq_err, msm_spi_error_irq,
|
|
IRQF_TRIGGER_RISING, pdev->name, master);
|
|
if (rc)
|
|
goto error_irq;
|
|
|
|
error_irq:
|
|
return rc;
|
|
}
|
|
|
|
static inline void msm_spi_get_clk_err(struct msm_spi *dd, u32 *spi_err) {}
|
|
static inline void msm_spi_ack_clk_err(struct msm_spi *dd) {}
|
|
static inline void msm_spi_set_qup_config(struct msm_spi *dd, int bpw) {}
|
|
|
|
static inline int msm_spi_prepare_for_write(struct msm_spi *dd) { return 0; }
|
|
static inline void msm_spi_start_write(struct msm_spi *dd, u32 read_count)
|
|
{
|
|
msm_spi_write_word_to_fifo(dd);
|
|
}
|
|
static inline void msm_spi_set_write_count(struct msm_spi *dd, int val) {}
|
|
|
|
static inline void msm_spi_complete(struct msm_spi *dd)
|
|
{
|
|
complete(&dd->transfer_complete);
|
|
}
|
|
|
|
static inline void msm_spi_enable_error_flags(struct msm_spi *dd)
|
|
{
|
|
writel_relaxed(0x0000007B, dd->base + SPI_ERROR_FLAGS_EN);
|
|
}
|
|
|
|
static inline void msm_spi_clear_error_flags(struct msm_spi *dd)
|
|
{
|
|
writel_relaxed(0x0000007F, dd->base + SPI_ERROR_FLAGS);
|
|
}
|
|
|
|
#else
|
|
/* In QUP the same interrupt line is used for input, output and error*/
|
|
static inline int msm_spi_request_irq(struct msm_spi *dd,
|
|
struct platform_device *pdev,
|
|
struct spi_master *master)
|
|
{
|
|
dd->irq_in = platform_get_irq(pdev, 0);
|
|
if (dd->irq_in < 0)
|
|
return -EINVAL;
|
|
|
|
return devm_request_irq(dd->dev, dd->irq_in, msm_spi_qup_irq,
|
|
IRQF_TRIGGER_HIGH, pdev->name, dd);
|
|
}
|
|
|
|
static inline void msm_spi_disable_irqs(struct msm_spi *dd)
|
|
{
|
|
disable_irq(dd->irq_in);
|
|
}
|
|
|
|
static inline void msm_spi_enable_irqs(struct msm_spi *dd)
|
|
{
|
|
enable_irq(dd->irq_in);
|
|
}
|
|
|
|
static inline void msm_spi_get_clk_err(struct msm_spi *dd, u32 *spi_err)
|
|
{
|
|
*spi_err = readl_relaxed(dd->base + QUP_ERROR_FLAGS);
|
|
}
|
|
|
|
static inline void msm_spi_ack_clk_err(struct msm_spi *dd)
|
|
{
|
|
writel_relaxed(QUP_ERR_MASK, dd->base + QUP_ERROR_FLAGS);
|
|
}
|
|
|
|
static inline void msm_spi_add_configs(struct msm_spi *dd, u32 *config, int n);
|
|
|
|
/* QUP has no_input, no_output, and N bits at QUP_CONFIG */
|
|
static inline void msm_spi_set_qup_config(struct msm_spi *dd, int bpw)
|
|
{
|
|
u32 qup_config = readl_relaxed(dd->base + QUP_CONFIG);
|
|
|
|
msm_spi_add_configs(dd, &qup_config, bpw-1);
|
|
writel_relaxed(qup_config | QUP_CONFIG_SPI_MODE,
|
|
dd->base + QUP_CONFIG);
|
|
}
|
|
|
|
static inline int msm_spi_prepare_for_write(struct msm_spi *dd)
|
|
{
|
|
if (msm_spi_set_state(dd, SPI_OP_STATE_RUN))
|
|
return -EINVAL;
|
|
if (msm_spi_set_state(dd, SPI_OP_STATE_PAUSE))
|
|
return -EINVAL;
|
|
return 0;
|
|
}
|
|
|
|
static inline void msm_spi_start_write(struct msm_spi *dd, u32 read_count)
|
|
{
|
|
if (read_count <= dd->input_fifo_size)
|
|
msm_spi_write_rmn_to_fifo(dd);
|
|
else
|
|
msm_spi_write_word_to_fifo(dd);
|
|
}
|
|
|
|
static inline void msm_spi_set_write_count(struct msm_spi *dd, int val)
|
|
{
|
|
writel_relaxed(val, dd->base + QUP_MX_WRITE_COUNT);
|
|
}
|
|
|
|
static inline void msm_spi_complete(struct msm_spi *dd)
|
|
{
|
|
dd->done = 1;
|
|
}
|
|
|
|
static inline void msm_spi_enable_error_flags(struct msm_spi *dd)
|
|
{
|
|
writel_relaxed(0x00000078, dd->base + SPI_ERROR_FLAGS_EN);
|
|
}
|
|
|
|
static inline void msm_spi_clear_error_flags(struct msm_spi *dd)
|
|
{
|
|
writel_relaxed(0x0000007C, dd->base + SPI_ERROR_FLAGS);
|
|
}
|
|
|
|
#endif
|
|
#endif
|