linux/drivers/tty/serial/ifx6x60.h
chao bi 31fe990488 serial:ifx6x60:Prevent data transfer when IFX6x60 port is shutdown
This patch is to implement following 2 places to avoid potential error when IFX6x60 port shutdown:
1) Clear Flag IFX_SPI_STATE_IO_AVAILABLE to disable data transfer when Modem port is shutdown;
2) Clear Flag IFX_SPI_STATE_IO_IN_PROGRESS and IFX_SPI_STATE_IO_READY when reopen port.
This is because last port shutdown may happen when SPI/DMA transfer is in progress, if the last
data transfer is not completed(for example due to modem reset), the Flag IFX_SPI_STATE_IO_IN_PROGRESS
will be set forever, so when IFX port is activated again, IFX_SPI_STATE_IO_IN_PROGRESS will prevent
transferring data forever. And if don't clear IFX_SPI_STATE_IO_READY, it may cause one more SPI frame
transferring in spit there is not data need to be transfer.

cc: liu chuansheng <chuansheng.liu@intel.com>
cc: Chen Jun <jun.d.chen@intel.com>
Signed-off-by: channing <chao.bi@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2012-11-01 08:50:01 -07:00

132 lines
3.4 KiB
C

/****************************************************************************
*
* Driver for the IFX spi modem.
*
* Copyright (C) 2009, 2010 Intel Corp
* Jim Stanley <jim.stanley@intel.com>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License 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.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA
*
*
*
*****************************************************************************/
#ifndef _IFX6X60_H
#define _IFX6X60_H
#define DRVNAME "ifx6x60"
#define TTYNAME "ttyIFX"
#define IFX_SPI_MAX_MINORS 1
#define IFX_SPI_TRANSFER_SIZE 2048
#define IFX_SPI_FIFO_SIZE 4096
#define IFX_SPI_HEADER_OVERHEAD 4
#define IFX_RESET_TIMEOUT msecs_to_jiffies(50)
/* device flags bitfield definitions */
#define IFX_SPI_STATE_PRESENT 0
#define IFX_SPI_STATE_IO_IN_PROGRESS 1
#define IFX_SPI_STATE_IO_READY 2
#define IFX_SPI_STATE_TIMER_PENDING 3
#define IFX_SPI_STATE_IO_AVAILABLE 4
/* flow control bitfields */
#define IFX_SPI_DCD 0
#define IFX_SPI_CTS 1
#define IFX_SPI_DSR 2
#define IFX_SPI_RI 3
#define IFX_SPI_DTR 4
#define IFX_SPI_RTS 5
#define IFX_SPI_TX_FC 6
#define IFX_SPI_RX_FC 7
#define IFX_SPI_UPDATE 8
#define IFX_SPI_PAYLOAD_SIZE (IFX_SPI_TRANSFER_SIZE - \
IFX_SPI_HEADER_OVERHEAD)
#define IFX_SPI_IRQ_TYPE DETECT_EDGE_RISING
#define IFX_SPI_GPIO_TARGET 0
#define IFX_SPI_GPIO0 0x105
#define IFX_SPI_STATUS_TIMEOUT (2000*HZ)
/* values for bits in power status byte */
#define IFX_SPI_POWER_DATA_PENDING 1
#define IFX_SPI_POWER_SRDY 2
struct ifx_spi_device {
/* Our SPI device */
struct spi_device *spi_dev;
/* Port specific data */
struct kfifo tx_fifo;
spinlock_t fifo_lock;
unsigned long signal_state;
/* TTY Layer logic */
struct tty_port tty_port;
struct device *tty_dev;
int minor;
/* Low level I/O work */
struct tasklet_struct io_work_tasklet;
unsigned long flags;
dma_addr_t rx_dma;
dma_addr_t tx_dma;
int modem; /* Modem type */
int use_dma; /* provide dma-able addrs in SPI msg */
long max_hz; /* max SPI frequency */
spinlock_t write_lock;
int write_pending;
spinlock_t power_lock;
unsigned char power_status;
unsigned char *rx_buffer;
unsigned char *tx_buffer;
dma_addr_t rx_bus;
dma_addr_t tx_bus;
unsigned char spi_more;
unsigned char spi_slave_cts;
struct timer_list spi_timer;
struct spi_message spi_msg;
struct spi_transfer spi_xfer;
struct {
/* gpio lines */
unsigned short srdy; /* slave-ready gpio */
unsigned short mrdy; /* master-ready gpio */
unsigned short reset; /* modem-reset gpio */
unsigned short po; /* modem-on gpio */
unsigned short reset_out; /* modem-in-reset gpio */
/* state/stats */
int unack_srdy_int_nb;
} gpio;
/* modem reset */
unsigned long mdm_reset_state;
#define MR_START 0
#define MR_INPROGRESS 1
#define MR_COMPLETE 2
wait_queue_head_t mdm_reset_wait;
void (*swap_buf)(unsigned char *buf, int len, void *end);
};
#endif /* _IFX6X60_H */