summaryrefslogtreecommitdiff
path: root/ANDROID_3.4.5/drivers/spi/wmt_spi.c
diff options
context:
space:
mode:
Diffstat (limited to 'ANDROID_3.4.5/drivers/spi/wmt_spi.c')
-rwxr-xr-xANDROID_3.4.5/drivers/spi/wmt_spi.c1347
1 files changed, 0 insertions, 1347 deletions
diff --git a/ANDROID_3.4.5/drivers/spi/wmt_spi.c b/ANDROID_3.4.5/drivers/spi/wmt_spi.c
deleted file mode 100755
index 7b301488..00000000
--- a/ANDROID_3.4.5/drivers/spi/wmt_spi.c
+++ /dev/null
@@ -1,1347 +0,0 @@
-/*++
- drivers/spi/wmt_spi.c
-
- Copyright (c) 2008 WonderMedia Technologies, Inc.
-
- 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,
- either version 2 of the License, or (at your option) any later version.
-
- 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, see <http://www.gnu.org/licenses/>.
-
- WonderMedia Technologies, Inc.
- 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C.
---*/
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/workqueue.h>
-#include <linux/ioport.h>
-#include <linux/dma-mapping.h>
-#include <linux/sched.h>
-
-#include <mach/hardware.h>
-#include <mach/wmt_gpio.h>
-
-//#define DEBUG 1 /* debug open */
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <mach/wmt-spi.h>
-
-#ifdef DEBUG
-#define spi_dbg(fmt, args...) printk(KERN_ERR "[%s]_%d: " fmt, __func__ , __LINE__, ## args)
-#define spi_trace() printk(KERN_ERR "trace in %s %d\n", __func__, __LINE__);
-#else
-#define spi_dbg(fmt, args...)
-#define spi_trace()
-#endif
-
-static unsigned int pllb_input_freq = 83333;
-static bool g_use_ss1 = false;
-static bool g_use_ss2 = false;
-static bool g_use_ss3 = false;
-
-/*
- * spi_set_reg32 - write a u32 value to spi register
- * @spi: spi controller's driver data
- * @reg_offset: register's offset address
- * @val: value register will be set
- */
-static inline void
-spi_set_reg32(struct wmt_spi *spi, u32 reg_offset, u32 val)
-{
- iowrite32(val, spi->regs_base + reg_offset);
-}
-
-/*
- * spi_get_reg32 - read a u32 value from spi register
- * @spi: spi controller's driver data
- * @reg_offset: register's offset address
- */
-static inline unsigned int
-spi_get_reg32(struct wmt_spi *spi, int reg_offset)
-{
- return ioread32(spi->regs_base + reg_offset);
-}
-
-/*
- * spi_setbit: write bit1 to related register's bit
- * @spi: spi controller's driver data
- * @offset: register's offset address
- * @mask: bit setting mask
- */
-static void
-spi_setbit(struct wmt_spi *spi, u32 reg_offset, u32 mask)
-{
- u32 tmp;
- tmp = spi_get_reg32(spi, reg_offset);
- tmp |= mask;
- spi_set_reg32(spi, reg_offset, tmp);
-}
-
-/*
- * spi_clrbit: write bit0 to related register's bit
- * @spi: spi controller's driver data
- * @offset: register's offset address
- * @mask: bit setting mask
- */
-static void
-spi_clrbit(struct wmt_spi *spi, u32 reg_offset, u32 mask)
-{
- u32 tmp;
- tmp = spi_get_reg32(spi, reg_offset);
- tmp &= ~mask;
- spi_set_reg32(spi, reg_offset, tmp);
-}
-
-/*
- * spi_write_fifo: write a u8 value to spi tx fifo
- * @spi: spi controller's driver data
- * @fifo_reg: spi tx fifo register offset
- * @val: value writen to spi tx fifo
- */
-static inline void
-spi_write_fifo(struct wmt_spi *spi, u32 fifo_reg, const u8 val)
-{
- iowrite8(val, spi->regs_base + fifo_reg);
-}
-
-/*
- * spi_read_fifo: read a u8 value from spi rx fifo
- * @spi: spi controller's driver data
- * @fifo_reg: spi rx fifo register offset
- */
-static inline u8
-spi_read_fifo(struct wmt_spi *spi, u32 fifo_reg)
-{
- return ioread8(spi->regs_base + fifo_reg);
-}
-
-/*
- * wmt_spi_clock_enable: set GPIO to SPI mode, ten enable spi
- * clock from Power management module and set default spi clock
- * dividor to 0x04 as default (93Mhz)
- */
-static inline void wmt_spi_clock_enable(void)
-{
- int timeout = POLLING_SPI_REG_TIMEOUT;
-
- GPIO_CTRL_GP12_SPI_BYTE_VAL &= ~(GPIO_SPI0_CLK |
- GPIO_SPI0_MOSI|
- GPIO_SPI0_MISO|
- GPIO_SPI0_SS0);
- PULL_EN_GP12_SPI_BYTE_VAL |= (GPIO_SPI0_CLK_PULL_EN |
- GPIO_SPI0_MOSI_PULL_EN|
- GPIO_SPI0_MISO_PULL_EN|
- GPIO_SPI0_SS0_PULL_EN);
- PULL_CTRL_GP12_SPI_BYTE_VAL |= (GPIO_SPI0_CLK_PULL_EN |
- GPIO_SPI0_MOSI_PULL_EN|
- GPIO_SPI0_MISO_PULL_EN);
- PULL_CTRL_GP12_SPI_BYTE_VAL &= ~GPIO_SPI0_CLK_PULL_UP;
- if (g_use_ss1 || g_use_ss2 || g_use_ss3)
- PIN_SHARING_SEL_4BYTE_VAL &= ~BIT7;
-#if 0
- /*Enable SPI function and disable GPIO function for related SPI pin*/
- GPIO_CTRL_GP11_SPI_BYTE_VAL &= ~(GPIO_SPI0_CLK |
- GPIO_SPI0_MOSI|
- GPIO_SPI0_MISO);
-
- GPIO_PULL_EN_GP11_SPI_BYTE_VAL |= ( GPIO_SPI0_CLK_PULL_EN |
- GPIO_SPI0_MISO_PULL_EN |
- GPIO_SPI0_MOSI_PULL_EN );
- GPIO_PULL_CTRL_GP11_SPI_BYTE_VAL |= (GPIO_SPI0_MISO_PULL_UP |
- GPIO_SPI0_MOSI_PULL_UP );
-
- GPIO_PULL_CTRL_GP11_SPI_BYTE_VAL &=~ (GPIO_SPI0_CLK_PULL_UP);
- if (g_use_ss0) {
- GPIO_CTRL_GP11_SPI_BYTE_VAL &= ~(GPIO_SPI0_SS);
- GPIO_PULL_EN_GP11_SPI_BYTE_VAL |= GPIO_SPI0_SS_PULL_EN;
- GPIO_PULL_CTRL_GP11_SPI_BYTE_VAL |= GPIO_SPI0_SS_PULL_UP;
- }
- if (g_use_ss1) {
- GPIO_CTRL_GP1_BYTE_VAL &= ~BIT2;
- GPIO_PULL_EN_GP1_BYTE_VAL |= BIT2;
- GPIO_PULL_CTRL_GP1_BYTE_VAL |= BIT2;
- GPIO_PIN_SHARING_SEL_4BYTE_VAL &= ~BIT5;
- }
- if (g_use_ss2) {
- GPIO_CTRL_GP31_BYTE_VAL &= ~BIT1;
- GPIO_PULL_EN_GP31_BYTE_VAL |= BIT1;
- GPIO_PULL_CTRL_GP31_BYTE_VAL |= BIT1;
- GPIO_PIN_SHARING_SEL_4BYTE_VAL |= BIT12;
- }
- if (g_use_ss3) {
- GPIO_CTRL_GP31_BYTE_VAL &= ~BIT2;
- GPIO_PULL_EN_GP31_BYTE_VAL |= BIT2;
- GPIO_PULL_CTRL_GP31_BYTE_VAL |= BIT2;
- GPIO_PIN_SHARING_SEL_4BYTE_VAL &= ~BIT4;
- }
-
-#endif
- /* clock open */
- auto_pll_divisor(DEV_SPI0, CLK_ENABLE, 0, 0);
- pllb_input_freq = auto_pll_divisor(DEV_SPI0, SET_DIV, 1, 100000);
- pllb_input_freq /= 1000;
-
- /* check if config successful */
- while (timeout--) {
- if (!(REG8_VAL(PMC_REG_BASE) & 0x04000000))
- return ;
- udelay(1);
- }
- printk(KERN_ERR "Enable SPI clock from PMC module failed\n!");
-}
-
-/*
- * wmt_spi_clock_disable: reset GPIO and disable spi clock from
- * Power management module
- */
-static inline void wmt_spi_clock_disable(void)
-{
- GPIO_CTRL_GP12_SPI_BYTE_VAL |= (GPIO_SPI0_CLK |
- GPIO_SPI0_MOSI|
- GPIO_SPI0_SS0|
- GPIO_SPI0_MISO);
-}
-
-/*
- * spi_is_busy: check spi controller(master) is busy or not
- * @spi: spi controller's driver data
- */
-static int spi_is_busy(struct wmt_spi *spi)
-{
- unsigned int timeout = POLLING_SPI_REG_TIMEOUT;
- while (timeout--) {
- if ((spi_get_reg32(spi, SPI_SR) & SPI_SR_BUSY_MASK) == 0)
- return 0;
- }
- return -EAGAIN;
-}
-
-/*
- * spi_enable: enable spi module
- * @spi: spi controller's driver data
- */
-static void spi_enable(struct wmt_spi *spi)
-{
- spi_setbit(spi, SPI_CR, SPI_CR_ME_MASK);
-}
-
-/*
- * spi_disable: disable spi module
- * @spi: spi controller's driver data
- */
-static void spi_disable(struct wmt_spi *spi)
-{
- if (spi_is_busy(spi)) {
- dev_warn(&spi->master->dev, "Disable spi controller failed\n");
- }
- spi_clrbit(spi, SPI_CR, SPI_CR_ME_MASK);
-}
-
-/*
- * spi_tx_is_finish: polling if data in tx fifo has been sent out
- * @spi: spi controller's driver data
- */
-static int spi_tx_is_finish(struct wmt_spi *spi)
-{
- unsigned int timeout = POLLING_SPI_REG_TIMEOUT;
- while (timeout--) {
- if (spi_get_reg32(spi, SPI_SR) | SPI_SR_TFEI_MASK)
- return 0;
- }
- return -EAGAIN;
-}
-
-/*
- * spi_rx_is_finish: polling if data in rx fifo has been read out
- * @spi: spi controller's driver data
- */
-static int spi_rx_is_finish(struct wmt_spi *spi)
-{
- unsigned int timeout = POLLING_SPI_REG_TIMEOUT;
- while (timeout--) {
- if ((spi_get_reg32(spi, SPI_SR) | SPI_SR_RFEI_MASK))
- return 0;
- }
- return -EAGAIN;
-}
-
-/*
- * wmt_spi_cs_active: enable chip select signal. SSN is driven
- * low to active if spi controller use SSN_CTRL_PROGRAM mode
- * @spi: spi controller's driver data
- */
-static inline void wmt_spi_cs_active(struct spi_device *spi_dev, struct wmt_spi *spi)
-{
- struct wmt_spi_hw *hw_info = spi->spi_hw_info;
-
- /* enable SSN */
- if (hw_info->ssn_ctrl == SSN_CTRL_PROGRAM)
- spi_clrbit(spi, SPI_DFCR, SPI_DFCR_DSV_MASK | SPI_DFCR_DSE_MASK);
-}
-
-/*
- * wmt_spi_cs_inactive: disable chip select signal. A SSN is driven
- * high to inactive if spi controller use SSN_CTRL_PROGRAM mode
- * @spi: spi controller's driver data
- */
-static inline void wmt_spi_cs_inactive(struct spi_device *spi_dev, struct wmt_spi *spi)
-{
- struct wmt_spi_hw *hw_info = spi->spi_hw_info;
-
- if (hw_info->ssn_ctrl == SSN_CTRL_PROGRAM)
- spi_setbit(spi, SPI_DFCR, SPI_DFCR_DSV_MASK | SPI_DFCR_DSE_MASK);
-}
-
-/*
- * get_spi_input_freq: get spi original input frequence from power
- * management module
- */
-static unsigned int get_spi_input_freq(void)
-{
- return pllb_input_freq;
-}
-
-/*
- * spi_set_clock_div: set clock divider in spi control register,
- * if the divisor is too low or too high, set spi working
- * frequency 5Mhz as default
- * @spi: spi controller's driver data
- * @speed_hz: spi working clock frequency, unit is hz
- */
-static void spi_set_clock_div(struct wmt_spi *spi, int speed_hz)
-{
- unsigned int divisor;
- unsigned int hw_freq = get_spi_input_freq()*1000; /* KHz to Hz */
-
- spi_clrbit(spi, SPI_CR, SPI_CR_TCD_MASK);
- if (!speed_hz)
- goto err;
-
- divisor = hw_freq/(2*speed_hz);
- if (divisor < 0 || divisor > 0x7ff) /* spi cr bit(21,31), max:0x7ff */
- goto err;
-
- spi_setbit(spi, SPI_CR, divisor << SPI_CR_TCD_SHIFT);
- return ;
-
-err:
- divisor = hw_freq/(2*SPI_DFLT_FREQ);
- spi_setbit(spi, SPI_CR, divisor << SPI_CR_TCD_SHIFT);
- dev_err(&spi->master->dev, "SPI frequency %dhz not support, " \
- "set %dhz as default\n", speed_hz, SPI_DFLT_FREQ);
- return ;
-}
-
-/*
- * spi_set_bit_order: set spi redeive/transmit significant bit order
- * @spi: spi controller's driver data
- * @mode: spi device working mode
- */
-static void spi_set_bit_order(struct wmt_spi *spi, u8 mode)
-{
- if (mode & SPI_LSB_FIRST)
- spi_setbit(spi, SPI_DFCR, SPI_DFCR_RSBO_MASK | SPI_DFCR_TSBO_MASK);
-}
-
-/*
- * spi_set_clock_mode: set spi clock polarity and phase (spi clock mode)
- * @spi: spi controller's driver data
- * @clk_mode: spi clock mode
- */
-static void spi_set_clock_mode(struct wmt_spi *spi, u8 clk_mode)
-{
- spi_clrbit(spi, SPI_CR, SPI_CR_CPHS_MASK);
- if (clk_mode > SPI_CLK_MODE3)
- goto err;
- spi_setbit(spi, SPI_CR, clk_mode << SPI_CR_CPHS_SHIFT);
- return ;
-err:
- spi_setbit(spi, SPI_CR, SPI_CLK_MODE3 << SPI_CR_CPHS_SHIFT);
- dev_err(&spi->master->dev, "clock mode err, set clock mode 3 as default\n");
- return ;
-}
-
-/*
- * spi_as_master: spi master/slave select
- * @spi: spi controller's driver data
- * @is_master: if spi configured as master, is_master = 1, else is_master = 0
- */
-static void spi_as_master(struct wmt_spi *spi, u8 is_master)
-{
- if (is_master)
- spi_clrbit(spi, SPI_CR, SPI_CR_MSMS_MASK);
- else
- spi_setbit(spi, SPI_CR, SPI_CR_MSMS_MASK);
-}
-
-/*
- * spi_reset_tx_fifo: reset spi transmit fifo
- * @spi: spi controller's driver data
- */
-static int spi_reset_tx_fifo(struct wmt_spi *spi)
-{
- unsigned int timeout = POLLING_SPI_REG_TIMEOUT;
- spi_setbit(spi, SPI_CR, SPI_CR_TFR_MASK);
- while (timeout--) {
- if ((spi_get_reg32(spi, SPI_CR) & SPI_CR_TFR_MASK) == 0)
- return 0;
- }
- return -1;
-}
-
-/*
- * spi_reset_rx_fifo: reset spi receive fifo
- * @spi: spi controller's driver data
- */
-static int spi_reset_rx_fifo(struct wmt_spi *spi)
-{
- unsigned int timeout = POLLING_SPI_REG_TIMEOUT;
- spi_setbit(spi, SPI_CR, SPI_CR_RFR_MASK);
- while (timeout--) {
- if ((spi_get_reg32(spi, SPI_CR) & SPI_CR_RFR_MASK) == 0)
- return 0;
- }
- return -EAGAIN;
-}
-
-/*
- * spi_reset_fifo: reset both spi transmit fifo and receive fifo
- * @spi: spi controller's driver data
- */
-static int spi_reset_fifo(struct wmt_spi *spi)
-{
- if (spi_reset_tx_fifo(spi))
- return -EAGAIN;
- if (spi_reset_rx_fifo(spi))
- return -EAGAIN;
- return 0;
-}
-
-/*
- * spi_reset: reset spi status register and reset spi tx and rx fifo
- * @spi: spi controller's driver data
- */
-static int spi_reset(struct wmt_spi *spi)
-{
- spi_set_reg32(spi, SPI_SR, ~0UL);
- return spi_reset_fifo(spi);
-}
-
-/*
- * spi_reset_transfer_speed: reset spi work frequency according
- * to spi_transfer
- * @spi: spi controller's driver data
- * @t: spi transfer
- */
-static void
-spi_reset_transfer_speed(struct wmt_spi *spi, struct spi_transfer *t)
-{
- if (t && t->speed_hz)
- spi_set_clock_div(spi, t->speed_hz);
-}
-
-/*
- * wmt_spi_regs_config: config spi registers according to the
- * information get from spi_device
- @spi_dev: Master side proxy for an SPI slave device
- */
-static int wmt_spi_regs_config(struct spi_device *spi_dev)
-{
- int ret = 0;
- u8 clk_mode;
- struct wmt_spi *wmt_spi;
- struct wmt_spi_slave *slave_info;
- struct wmt_spi_hw *hw_info;
-
- wmt_spi = spi_master_get_devdata(spi_dev->master);
- slave_info = spi_dev->controller_data;
- hw_info = wmt_spi->spi_hw_info;
-
- /* clear spi control register */
- spi_set_reg32(wmt_spi, SPI_CR, 0x00UL);
- /* clear spi status register */
- spi_set_reg32(wmt_spi, SPI_SR, ~0UL);
- /* spi cre register */
- spi_set_reg32(wmt_spi, SPI_CRE, 0x20);
-
- /* reset tx and rx fifo */
- ret = spi_reset_fifo(wmt_spi);
- if (ret)
- goto err;
- /* setting spi controller register */
- /* 1. set spi clock divider */
- spi_set_clock_div(wmt_spi, spi_dev->max_speed_hz);
- /* 2 set clock mode */
- clk_mode = (spi_dev->mode & (BIT0 | BIT1));
- spi_set_clock_mode(wmt_spi, clk_mode);
- /* 3. spi as master */
- spi_as_master(wmt_spi, 1);
- /* 4. slave selection */
- /*
- spi_setbit(wmt_spi, SPI_CR, spi_dev->chip_select << SPI_CR_SS_SHIFT);
- */
- /*for wm3465 A0*/
- spi_setbit(wmt_spi, SPI_CR, 0 << SPI_CR_SS_SHIFT);
-
- /* setting spi data format control register */
- /* 1. port mode setting */
- if (PORT_MODE_PTP == hw_info->port_mode)
- spi_setbit(wmt_spi, SPI_DFCR, SPI_DFCR_SPM_MASK);
- /* 2. spi tx/rx significant bit order */
- spi_set_bit_order(wmt_spi, spi_dev->mode);
- /* 3. ssn control setting */
- if (SSN_CTRL_PROGRAM == hw_info->ssn_ctrl) {
- if ((clk_mode & SPI_CR_CPHS_MASK) == 0) {
- dev_warn(&spi_dev->dev, "SSN_ctrl conflict with clock mode\n");
- /* do not abort now, the conflict is not a serious problem,
- driver can handle this well, so we work on */
- goto err;
- }
- spi_setbit(wmt_spi, SPI_DFCR, SPI_DFCR_SC_MASK);
- }
- return 0;
-
-err:
- dev_err(&wmt_spi->pdev->dev, "SPI config register error\n");
- return ret;
-}
-
-/*
- * wmt_spi_fifo_tx: transmit data by spi TX_FIFO.
- * @spi: spi controller's driver data
- * @tx_buf: data transmited by spi tx fifo
- * @len: tx buffers length. Note: len is not checked in this function,
- * and wmt spi fifo size is 32bytes, so caller must be sure
- * len <= 32bytes
- */
-static void
-wmt_spi_fifo_tx(struct wmt_spi *spi, const u8 *tx_buf, int len)
-{
- int i;
- /* load data to tx fifo */
- if (tx_buf) {
- for (i = 0; i < len; i++)
- spi_write_fifo(spi, SPI_TXFIFO, tx_buf[i]);
- } /* load idle data to tx fifo */else {
- for (i = 0; i < len; i++)
- spi_write_fifo(spi, SPI_TXFIFO, 0x00);
- }
-}
-
-/*
- * wmt_spi_write_read: spi transfer routine
- * @spi_dev: Master side proxy for an SPI slave device
- * @t: spi transfer
- * wmt spi transmit fifo is SPI_FIFO_SIZE(32bytes),
- * so if transmit data more than 32bytes, we need transmit
- * those data more than one time
- **/
-static int
-wmt_spi_write_read(struct spi_device *spi, struct spi_transfer *t)
-{
- int i = 0;
- const u8 *tx = t->tx_buf;
- u8 *rx = t->rx_buf;
- unsigned int cnt = t->len;
- struct wmt_spi *wmt_spi = spi_master_get_devdata(spi->master);
-
- /* reset spi first */
- if (spi_reset(wmt_spi))
- goto out;
- /* if data length more than SPI_FIFO_SIZE(32bytes) */
- while (cnt >= SPI_FIFO_SIZE) {
- /* load data form tx_buf to tx_fifo */
- wmt_spi_fifo_tx(wmt_spi, tx, SPI_FIFO_SIZE);
- /* send data */
- spi_enable(wmt_spi);
- /* waitting for send finish */
- if (spi_tx_is_finish(wmt_spi))
- goto out;
- /* data send has finished */
- spi_disable(wmt_spi);
- /* read data and stroe in rx_buf */
- if (rx) {
- for (i = 0; i < SPI_FIFO_SIZE; i++)
- *rx++ = spi_read_fifo(wmt_spi, SPI_RXFIFO);
- }
- /* check if rx finish */
- if (spi_rx_is_finish(wmt_spi))
- goto out;
- if (tx)
- tx += SPI_FIFO_SIZE;
- cnt -= SPI_FIFO_SIZE;
- if (t->speed_hz < 5*1000*1000)
- udelay(2000);
- /* reset for the next transfer */
- if (spi_reset(wmt_spi))
- goto out;
- }
- /* remain data transfer */
- if (cnt && cnt < SPI_FIFO_SIZE) {
- wmt_spi_fifo_tx(wmt_spi, tx, cnt);
- spi_enable(wmt_spi);
- if (spi_tx_is_finish(wmt_spi))
- goto out;
- spi_disable(wmt_spi);
- if (rx) {
- for (; cnt > 0; cnt--)
- *rx++ = spi_read_fifo(wmt_spi, SPI_RXFIFO);
- } else {
- for (; cnt > 0; cnt--)
- spi_read_fifo(wmt_spi, SPI_RXFIFO);
- }
- }
-out:
- return (t->len - cnt);
-}
-
-/*
- * spi_dsr_w: spi dma transmit callback function
- * @arg: point to wmt_spi
- **/
-static void spi_dsr_w(void *arg)
-{
- struct wmt_spi *spi = (struct wmt_spi *)arg;
- struct wmt_spi_dma *spi_dma = spi->spi_dma_info;
- spi_dma->tx_ack = 1;
- wake_up_interruptible(&spi_dma->tx_event);
-}
-
-/*
- * spi_dsr_r: spi dma receive callback function
- * @arg: point to wmt_spi
- **/
-static void spi_dsr_r(void *arg)
-{
- struct wmt_spi *spi = (struct wmt_spi *)arg;
- struct wmt_spi_dma *spi_dma = spi->spi_dma_info;
- spi_dma->rx_ack = 1;
- wake_up_interruptible(&spi_dma->rx_event);
-}
-
-/*
- * wmt_spi_dma_write_read: spi transfer (use DMA mode)
- * @spi_dev: Master side proxy for an SPI slave device
- * @t: spi transfer1
- **/
-static int
-wmt_spi_dma_write_read(struct spi_device *spi_dev, struct spi_transfer *t)
-{
- struct wmt_spi *wmt_spi = spi_master_get_devdata(spi_dev->master);
- struct wmt_spi_dma *spi_dma = wmt_spi->spi_dma_info;
- wait_queue_head_t *event = &spi_dma->tx_event;
- volatile int *ack = &spi_dma->tx_ack;
- unsigned int transfered_cnt = 0;
- u32 ctrl;
-
- /* spi dma transfer need cs inactive first*/
- wmt_spi_cs_inactive(spi_dev, wmt_spi);
- if (t->speed_hz > 15000000)
- spi_set_clock_div(wmt_spi, 15000000);
- ctrl = spi_get_reg32(wmt_spi, SPI_CR);
- ctrl |= SPI_CR_DRC_MASK | SPI_CR_RFTS_MASK | SPI_CR_TFTS_MASK;
- spi_set_reg32(wmt_spi, SPI_CR, ctrl);
- /* reset spi fifo */
- if (spi_reset(wmt_spi))
- goto out;
- /* tx dma buffer prepare */
- if (t->tx_buf)
- memcpy(spi_dma->io_waddr, t->tx_buf, t->len);
- /* tx dma request */
- if (wmt_request_dma(&spi_dma->tx_ch, "wmt_spi_tx",
- spi_dma->tx_config.DeviceReqType,
- spi_dsr_w, wmt_spi)) {
- dev_err(&spi_dev->dev, "SPI request TX DMA failed\n");
- goto out;
- }
- /* rx dma request and start */
- if (t->rx_buf) {
- if (wmt_request_dma(&spi_dma->rx_ch, "wmt_spi_rx",
- spi_dma->rx_config.DeviceReqType,
- spi_dsr_r, wmt_spi)) {
- dev_err(&spi_dev->dev, "SPI request RX DMA failed\n");
- goto free_tx_dma;
- }
- wmt_setup_dma(spi_dma->rx_ch, spi_dma->rx_config);
- wmt_start_dma(spi_dma->rx_ch, spi_dma->phys_raddr, 0x00, t->len);
- event = &spi_dma->rx_event;
- ack = &spi_dma->rx_ack;
- }
- /* transmit dma setup and start */
- wmt_setup_dma(spi_dma->tx_ch, spi_dma->tx_config);
- wmt_start_dma(spi_dma->tx_ch, spi_dma->phys_waddr, 0x00, t->len + 7);
- /* enable spi and active chipselect signal */
- msleep(2);
- spi_enable(wmt_spi);
- /* waitting for transmit finish */
- msleep(2);
- wmt_spi_cs_active(spi_dev, wmt_spi);
- /* waitting transfer finish */
- if (!wait_event_interruptible_timeout(*event, *ack, 100)) {
- dev_err(&spi_dev->dev, "SPI DMA transfer failed\n");
- goto out;
- }
- transfered_cnt = t->len;
- /* if RX buf is not empty, copy received data from dma to t->rx_buf */
- if (t->rx_buf) {
- memcpy(t->rx_buf, spi_dma->io_raddr, t->len);
- wmt_free_dma(spi_dma->rx_ch);
- memset(spi_dma->io_raddr, 0x00, t->len);
- }
-free_tx_dma:
- wmt_free_dma(spi_dma->tx_ch);
- memset(spi_dma->io_waddr, 0x00, t->len);
-out:
- spi_disable(wmt_spi);
- spi_dma->rx_ack = spi_dma->tx_ack = 0;
- return transfered_cnt;
-}
-
-/*
- * wmt_spi_work: wmt spi controller work queue routine function.
- * Check every message which queued in workqueue (wmt_spi->queue),
- * if all things correct, message dequeued and begin transfer routine
- * @work: work which queued in spi controller's work queue
- */
-static void wmt_spi_work(struct work_struct *work)
-{
- struct wmt_spi *wmt_spi;
- struct wmt_spi_slave *spi_ctrl;
-
- wmt_spi = container_of(work, struct wmt_spi, work);
- spin_lock_irq(&wmt_spi->spinlock);
-
- while (!list_empty(&wmt_spi->queue)) {
- int status = 0;
- u8 cs_active = 0;
- struct spi_message *m = NULL;
- struct spi_transfer *t = NULL;
- struct spi_device *spi;
-
- m = container_of(wmt_spi->queue.next, struct spi_message, queue);
- spi_ctrl = m->spi->controller_data;
-
- list_del_init(&m->queue);
- spin_unlock_irq(&wmt_spi->spinlock);
-
- spi = m->spi;
- status = wmt_spi_regs_config(m->spi);
- if (status < 0)
- goto msg_done;
- /* check every transfer which queued in message,
- * if all things right, begin data transfer */
- list_for_each_entry(t, &m->transfers, transfer_list) {
- spi_reset_transfer_speed(wmt_spi, t);
-
- if (!cs_active) {
- wmt_spi_cs_active(spi, wmt_spi);
- cs_active = 1;
- }
-
- /* data transfer begins here */
- if (t->len) {
- if (wmt_spi->spi_hw_info->dma_support && m->is_dma_mapped
- && spi_ctrl->dma_en && t->len > SPI_FIFO_SIZE) {
- m->actual_length += wmt_spi_dma_write_read(m->spi, t);
- } else {
- m->actual_length += wmt_spi_write_read(m->spi, t);
- }
- }
- /* some device need this feature support */
- if (t->delay_usecs)
- udelay(t->delay_usecs);
-
- /* if cs need change in next transfer, just inactive it */
- if (t->cs_change) {
- wmt_spi_cs_inactive(spi, wmt_spi);
- cs_active = 0;
- }
- }
-
-msg_done:
- if (status < 0)
- dev_err(&wmt_spi->master->dev, "SPI transfer error!\n");
- if (cs_active)
- wmt_spi_cs_inactive(spi, wmt_spi);
- m->status = status;
- if (m->complete && m->context)
- m->complete(m->context);
- spin_lock_irq(&wmt_spi->spinlock);
- }
- spin_unlock(&wmt_spi->spinlock);
-}
-
-/*
- * bits_per_word_is_support: check if spi controller can support
- * this bits_per_word type or not
- * @spi: spi controller's driver data
- * @bit_per_word: bits_per_word type will be check
- */
-static int
-bits_per_word_is_support(struct wmt_spi *spi, u8 bit_per_word)
-{
- int ret = 0;
- struct wmt_spi_hw *hw_info = spi->spi_hw_info;
-
- if ((bit_per_word != 8) && (bit_per_word != 16 )) {
- ret = -EINVAL;
- goto err;
- }
-
- if ((bit_per_word == 8) &&
- !(hw_info->bits_per_word_en & BITS8_PER_WORD_EN)) {
- ret = -EINVAL;
- goto err;
- }
-
- if ((bit_per_word == 16) &&
- !(hw_info->bits_per_word_en & BITS16_PER_WORD_EN)) {
- ret = -EINVAL;
- goto err;
- }
-err:
- return ret;
-}
-
-/*
- * speed_hz_is_support: check spi controller can support this
- * frequency or not
- * @spi: spi controller's driver data
- * @speed_hz: frequency spi controller will working with
- */
-static int speed_hz_is_support(struct wmt_spi *spi, u32 speed_hz)
-{
- int ret = 0;
- struct wmt_spi_hw *hw_info = spi->spi_hw_info;
-
- if (speed_hz < hw_info->min_freq_hz) {
- ret = -EINVAL;
- goto err;
- }
-
- if (speed_hz > hw_info->max_freq_hz) {
- ret = -EINVAL;
- }
-
-err:
- return ret;
-}
-
-/*
- * wmt_spi_transfer: check transfers queued in spi message,
- * then queued spi message in workqueue
- *@spi_dev: Master side proxy for an SPI slave device
- * @m: spi message which will be added to the queue
- */
-/* bidirectional bulk transfers
- *
- * + The transfer() method may not sleep; its main role is
- * just to add the message to the queue.
- * + For now there's no remove-from-queue operation, or
- * any other request management
- * + To a given spi_device, message queueing is pure fifo
- *
- * + The master's main job is to process its message queue,
- * selecting a chip then transferring data
- * + If there are multiple spi_device children, the i/o queue
- * arbitration algorithm is unspecified (round robin, fifo,
- * priority, reservations, preemption, etc)
- *
- * + Chipselect stays active during the entire message
- * (unless modified by spi_transfer.cs_change != 0).
- * + The message transfers use clock and SPI mode parameters
- * previously established by setup() for this device
- */
-static int
-wmt_spi_transfer(struct spi_device *spi_dev, struct spi_message *m)
-{
- struct wmt_spi *wmt_spi = spi_master_get_devdata(spi_dev->master);
- struct spi_transfer *t = NULL;
- unsigned long flags = 0;
-
- m->actual_length = 0;
- m->status = 0;
- /* reject invalid messages and transfers */
- if (list_empty(&m->transfers) || !m->complete) {
- //if (list_empty(&m->transfers)) { // for none sleep
- dev_err(&spi_dev->dev, "msg rejected: invalid message of transfer\n");
- goto msg_reject;
- }
- /* transfers members bits_per_word and speed_hz checking and setting */
- list_for_each_entry(t, &m->transfers, transfer_list) {
- if ((!t->tx_buf) && (!t->rx_buf) && t->len) {
- dev_err(&spi_dev->dev, "msg rejected: invalid message data\n");
- goto msg_reject;
- }
-
- /* checking transfer length */
- if (t->len > wmt_spi->spi_hw_info->max_transfer_length) {
- dev_err(&spi_dev->dev, "msg rejected: transfer lenth can not be"\
- "bigger than %d, please split it into smaller chunks"\
- "and submit them separately\n",
- wmt_spi->spi_hw_info->max_transfer_length);
- goto msg_reject;
- }
-
- /* checking and resetting transfer bits_per_word */
- if (!t->bits_per_word
- || bits_per_word_is_support(wmt_spi, t->bits_per_word))
- t->bits_per_word = spi_dev->bits_per_word;
-
- /* checking and resetting transfer speed_hz */
- if (!t->speed_hz || speed_hz_is_support(wmt_spi, t->speed_hz))
- t->speed_hz = spi_dev->max_speed_hz;
- }
- spin_lock_irqsave(&wmt_spi->spinlock, flags);
- /* add this message into spi's queue */
- list_add_tail(&m->queue, &wmt_spi->queue);
- /* doing message transfer routine in spi work */
- queue_work(wmt_spi->workqueue, &wmt_spi->work);
- spin_unlock_irqrestore(&wmt_spi->spinlock, flags);
- return 0;
-
-msg_reject:
- m->status = -EINVAL;
- if (m->complete)
- m->complete(m->context);
- return -EINVAL;
-}
-
-/*
- * wmt_spi_setup: updates the device mode, bits_per_word and clocking
- * records used by a device's SPI controller; protocol code may call
- * this. This must fail if an unrecognized or unsupported mode is
- * requested.It's always safe to call this unless transfers are pending
- * on the device whose settings are being modified.
- * @spi_dev: Master side proxy for an SPI slave device
- */
-#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_LOOP | SPI_LSB_FIRST)
-static int wmt_spi_setup(struct spi_device *spi_dev)
-{
- int ret = 0;
- struct wmt_spi *wmt_spi;
- struct wmt_spi_slave *slave_info;
- struct wmt_spi_hw *hw_info;
-
- wmt_spi = spi_master_get_devdata(spi_dev->master);
- slave_info = spi_dev->controller_data;
- hw_info = wmt_spi->spi_hw_info;
-
- /* mode checking */
- if (spi_dev->mode & ~MODEBITS) {
- dev_err(&spi_dev->dev, "SPI unsupported this mode 0x%08x\n",
- spi_dev->mode & ~MODEBITS);
- ret = -EINVAL;
- goto err;
- }
-
- /* bits_per_word checking */
- if (!spi_dev->bits_per_word)
- spi_dev->bits_per_word = slave_info->bits_per_word;
-
- if (spi_dev->bits_per_word) {
- if (bits_per_word_is_support(wmt_spi, spi_dev->bits_per_word)) {
- if (bits_per_word_is_support(wmt_spi,
- slave_info->bits_per_word)) {
- dev_err(&spi_dev->dev, "SPI unsupport %d and %dbits_per_word\n",
- spi_dev->bits_per_word, slave_info->bits_per_word);
- ret = -EINVAL;
- goto err;
- }
- spi_dev->bits_per_word = slave_info->bits_per_word;
- }
- }
-
- /* max_speed_hz checking */
- if ((spi_dev->max_speed_hz == 0) ||
- (spi_dev->max_speed_hz > hw_info->max_freq_hz))
- spi_dev->max_speed_hz = hw_info->max_freq_hz;
-
- if (spi_dev->max_speed_hz < hw_info->min_freq_hz) {
- dev_err(&spi_dev->dev, "SPI unspport speed lower than %dhz\n",
- hw_info->min_freq_hz);
- ret = -EINVAL;
- goto err;
- }
- return 0;
-
-err:
- dev_err(&spi_dev->dev, "SPI setup spi device failed!\n");
- return ret;
-}
-
-/*
- * wmt_spi_cleanup: called on module_exit to free memory
- * provided by spi_master
- * @wmt_spi: spi controller driver data
- */
-static void wmt_spi_cleanup(struct wmt_spi *wmt_spi)
-{
- if (wmt_spi->spi_hw_info)
- kfree(wmt_spi->spi_hw_info);
- wmt_spi->spi_hw_info = NULL;
-
- if (wmt_spi->spi_dma_info)
- kfree(wmt_spi->spi_dma_info);
- wmt_spi->spi_dma_info = NULL;
-}
-
-/*
- * spi_get_hw_info: get spi controller's configuration infomation
- * form platform device
- * @pdev: spi platform device structure
- */
-static inline void *spi_get_hw_info(struct platform_device *pdev)
-{
- return pdev->dev.platform_data;
-}
-
-/*
- * wmt_spi_dma_init: request spi dma memory and initialize spi dma info
- if dma supported
- * @spi: spi controller's driver data
- */
-static int wmt_spi_dma_init(struct wmt_spi *spi)
-{
- int ret = 0;
- unsigned int dma_size;
-
- if (!spi->spi_hw_info)
- goto out;
- if (!spi->spi_hw_info->dma_support)
- goto out;
- spi->spi_dma_info = kmalloc(sizeof(struct wmt_spi_dma), GFP_KERNEL);
- if (!spi->spi_dma_info) {
- ret = -ENOMEM;
- dev_err(&spi->pdev->dev, "SPI allocating dma info memory failed\n");
- goto out;
- }
- dma_size = spi->spi_hw_info->max_transfer_length;
- /* dma read config */
- spi->spi_dma_info->rx_ch = ~0UL;
- spi->spi_dma_info->rx_config.ChunkSize = SPI_DMA_CHUNK_SIZE;
- spi->spi_dma_info->rx_config.DefaultCCR = SPI_RX_DMA_CFG;
- spi->spi_dma_info->rx_config.DeviceReqType = SPI0_DMA_RX_REQ;
- spi->spi_dma_info->rx_config.MIF1addr = SPI0_BASE_ADDR + SPI_RXFIFO;
- spi->spi_dma_info->io_raddr = dma_alloc_coherent(&spi->pdev->dev,
- dma_size,
- &spi->spi_dma_info->phys_raddr,
- GFP_KERNEL | GFP_DMA);
- if (!spi->spi_dma_info->io_raddr) {
- ret = -ENOMEM;
- dev_err(&spi->pdev->dev, "SPI allocate rdma failed\n");
- goto out;
- }
- memset(spi->spi_dma_info->io_raddr, 0x00, dma_size);
- spi->spi_dma_info->rx_config.MIF0addr = (ulong)spi->spi_dma_info->io_raddr;
- init_waitqueue_head(&spi->spi_dma_info->rx_event);
- spi->spi_dma_info->rx_ack = 0;
- /* dma write config */
- spi->spi_dma_info->tx_ch = ~0UL;
- spi->spi_dma_info->tx_config.ChunkSize = SPI_DMA_CHUNK_SIZE;
- spi->spi_dma_info->tx_config.DefaultCCR = SPI_TX_DMA_CFG;
- spi->spi_dma_info->tx_config.DeviceReqType = SPI0_DMA_TX_REQ;
- spi->spi_dma_info->tx_config.MIF1addr = SPI0_BASE_ADDR + SPI_TXFIFO;
- spi->spi_dma_info->io_waddr = dma_alloc_coherent(&spi->pdev->dev,
- dma_size + 7,
- &spi->spi_dma_info->phys_waddr,
- GFP_KERNEL | GFP_DMA);
- if (!spi->spi_dma_info->io_waddr) {
- ret = -ENOMEM;
- dev_err(&spi->pdev->dev, "SPI allocate wdma failed\n");
- goto free_spi_rx_dma;
- }
- memset(spi->spi_dma_info->io_waddr, 0x00, dma_size + 7);
- spi->spi_dma_info->tx_config.MIF0addr = (ulong)spi->spi_dma_info->io_waddr;
- init_waitqueue_head(&spi->spi_dma_info->tx_event);
- spi->spi_dma_info->tx_ack = 0;
- return 0;
-
-free_spi_rx_dma:
- dma_free_coherent(&spi->pdev->dev,dma_size,spi->spi_dma_info->io_raddr,
- spi->spi_dma_info->phys_raddr);
-out:
- return ret;
-}
-
-/*
- * wmt_spi_dma_release: release spi dma memory if dma supported
- * @spi: spi controller's driver data
- */
-static void wmt_spi_dma_release(struct wmt_spi *spi)
-{
- if (!spi->spi_hw_info)
- goto out;
- if (!spi->spi_hw_info->dma_support)
- goto out;
-
- dma_free_coherent(&spi->pdev->dev,
- spi->spi_hw_info->max_transfer_length,
- spi->spi_dma_info->io_raddr,
- spi->spi_dma_info->phys_raddr);
- dma_free_coherent(&spi->pdev->dev,
- spi->spi_hw_info->max_transfer_length + 7,
- spi->spi_dma_info->io_waddr,
- spi->spi_dma_info->phys_waddr);
-out:
- return ;
-}
-
-static int __devinit wmt_spi_probe(struct platform_device *pdev)
-{
- int ret;
- struct device *dev = &pdev->dev;
- struct spi_master *master;
- struct wmt_spi *wmt_spi;
- struct wmt_spi_hw *wmt_dev_info;
- struct resource *res;
-
- /* SPI master allocation */
- master = spi_alloc_master(dev, sizeof(struct wmt_spi));
- if (!master) {
- ret = -ENOMEM;
- dev_err(dev, "SPI master allocation failed!\n");
- goto the_end;
- }
-
- /* spi controller structure initialization */
- wmt_spi = (struct wmt_spi *)spi_master_get_devdata(master);
- memset(wmt_spi, 0x00, sizeof(struct wmt_spi));
- wmt_spi->master = spi_master_get(master);
- wmt_spi->pdev = pdev;
- wmt_dev_info = spi_get_hw_info(pdev);
- wmt_spi->spi_hw_info = kmalloc(sizeof(struct wmt_spi_hw), GFP_KERNEL);
- if (!wmt_spi->spi_hw_info) {
- dev_err(dev, "SPI allocating hardware info memory failed\n");
- ret = -ENOMEM;
- goto release_master;
- }
- memset(wmt_spi->spi_hw_info, 0x00, sizeof(struct wmt_spi_hw));
- memcpy(wmt_spi->spi_hw_info, wmt_dev_info,
- sizeof(struct wmt_spi_hw));
-
- /* spi master initialization */
- master->bus_num = pdev->id;
- master->num_chipselect = wmt_dev_info->num_chipselect;
- master->setup = wmt_spi_setup;
- master->transfer = wmt_spi_transfer;
-
- /* the spi->mode bits understood by this driver: */
- master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
-
- platform_set_drvdata(pdev, wmt_spi);
-
- /* device resource request */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- ret = -ENXIO;
- dev_err(dev, "SPI getting platform resource failed\n");
- goto release_hw_info;
- }
-#if 0
- if (!request_mem_region(res->start, res->end-res->start+1, pdev->name)) {
- ret = -ENXIO;
- dev_err(dev, "SPI request mem region failed\n");
- goto release_hw_info;
- }
- wmt_spi->regs_base = ioremap(res->start, res->end - res->start + 1);
-#endif
- wmt_spi->regs_base = (void __iomem *)SPI0_BASE_ADDR;
- if (!wmt_spi->regs_base) {
- ret = -ENXIO;
- dev_err(dev, "SPI ioremap failed!\n");
- goto release_region;
- }
-
- if (wmt_dev_info->dma_support) {
- if (wmt_spi_dma_init(wmt_spi)) {
- ret = -ENXIO;
- wmt_dev_info->dma_support = 0;
- dev_err(dev, "SPI dma init failed\n");
- goto release_ioremap;
- }
- }
-
- /* work queue create */
- spin_lock_init(&wmt_spi->spinlock);
- INIT_LIST_HEAD(&wmt_spi->queue);
- INIT_WORK(&wmt_spi->work, wmt_spi_work);
- init_waitqueue_head(&wmt_spi->waitq);
- wmt_spi->workqueue = create_singlethread_workqueue("wmt_spi");
- if (NULL == wmt_spi->workqueue) {
- ret = -ENXIO;
- dev_err(dev, "SPI create workqueue failed!\n");
- goto release_dma;
- }
- /* power and clock open */
- wmt_spi_clock_enable();
-
- /* registe spi master at last */
- ret = spi_register_master(master);
- if (ret) {
- dev_err(dev, "SPI register master failed\n");
- goto release_workqueue;
- }
-
- printk(KERN_INFO "WMT EVB SPI Controlor Driver OK!\n");
- return 0;
-
-release_workqueue:
- wmt_spi_clock_disable();
- destroy_workqueue(wmt_spi->workqueue);
-release_dma:
- wmt_spi_dma_release(wmt_spi);
-release_ioremap:
- iounmap(wmt_spi->regs_base);
-release_region:
- release_mem_region(res->start, res->end - res->start + 1);
-release_hw_info:
- kfree(wmt_spi->spi_hw_info);
- platform_set_drvdata(pdev, NULL);
-release_master:
- spi_master_put(master);
-the_end:
- dev_err(dev, "WMT EVB SPI Controlor Probe Failed!\n");
- return ret;
-}
-
-static int wmt_spi_stop_queue(struct wmt_spi *spi)
-{
- unsigned long flags;
- unsigned limit = 500;
- int status = 0;
-
- spin_lock_irqsave(&spi->spinlock, flags);
-
- while (!list_empty(&spi->queue) && limit--) {
- spin_unlock_irqrestore(&spi->spinlock, flags);
- msleep(10);
- spin_lock_irqsave(&spi->spinlock, flags);
- }
-
- if (!list_empty(&spi->queue))
- status = -EBUSY;
-
- spin_unlock_irqrestore(&spi->spinlock, flags);
-
- return status;
-}
-
-static int __devexit wmt_spi_remove(struct platform_device *pdev)
-{
- struct wmt_spi *spi;
- struct wmt_spi_hw *spi_hw_info;
- struct resource *res;
-
- spi = (struct wmt_spi *)platform_get_drvdata(pdev);
- spi_hw_info = spi_get_hw_info(pdev);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
- /* stop spi message queue */
- wmt_spi_stop_queue(spi);
- /* SSN inactive */
- /*
- wmt_spi_cs_inactive(spi);
- */
- spi_disable(spi);
- /* clock and power off */
- wmt_spi_clock_disable();
- /* work queue flush and destory */
- flush_workqueue(spi->workqueue);
- destroy_workqueue(spi->workqueue);
- /* dma free if dma support and enable */
- wmt_spi_dma_release(spi);
- /* irq free */
- if (spi->irq)
- free_irq(spi->irq, spi);
- /* release requested resource */
- iounmap(spi->regs_base);
- release_mem_region(res->start, res->end - res->start + 1);
- /* driver data entry reset */
- platform_set_drvdata(pdev, NULL);
- /* free memory provide by spi master */
- wmt_spi_cleanup(spi);
- /* spi master unregister and free */
- spi_unregister_master(spi->master);
- spi_master_put(spi->master);
-
- return 0;
-}
-
-#ifdef CONFIG_PM
-static int
-wmt_spi_suspend(struct platform_device *pdev, pm_message_t state)
-{
- int ret = 0;
- struct wmt_spi *spi = platform_get_drvdata(pdev);
- state = state;
-
- spi_dbg("Enter\n");
- ret = wmt_spi_stop_queue(spi);
- if (ret) {
- dev_warn(&pdev->dev, "suspend wmt spi failed\n");
- return ret;
- }
- /*
- wmt_spi_cs_inactive(spi);
- */
- spi_disable(spi);
-
- spi_dbg("Exit\n");
- return 0;
-}
-
-static int wmt_spi_resume(struct platform_device *pdev)
-{
- struct wmt_spi *spi = platform_get_drvdata(pdev);
-
- spi_dbg("Enter\n");
- /* hardware reset */
- wmt_spi_clock_enable();
- /* start msg queue */
- queue_work(spi->workqueue, &spi->work);
-
- spi_dbg("Exit\n");
- return 0;
-}
-#else
-#define wmt_spi_suspend NULL
-#define wmt_spi_resume NULL
-#endif /* CONFIG_PM */
-
-static struct platform_driver wmt_spi_driver = {
- .driver = {
- .name = "wmt_spi_0",
- .owner = THIS_MODULE,
- },
- .suspend = wmt_spi_suspend,
- .resume = wmt_spi_resume,
- .remove = __devexit_p(wmt_spi_remove),
-};
-
-static int __init wmt_spi_init(void)
-{
- return platform_driver_probe(&wmt_spi_driver, wmt_spi_probe);
-}
-module_init(wmt_spi_init);
-
-static void __exit wmt_spi_exit(void)
-{
- platform_driver_unregister(&wmt_spi_driver);
-}
-module_exit(wmt_spi_exit);
-
-MODULE_AUTHOR("WonderMedia Technologies, Inc.");
-MODULE_DESCRIPTION("WMT SPI Controller Driver");
-MODULE_LICENSE("GPL");