serial: remove unused rk drivers

Change-Id: If7356271263694862030136aed9b32016e6327e4
Signed-off-by: Tao Huang <huangtao@rock-chips.com>
This commit is contained in:
Tao Huang 2018-01-25 10:42:25 +08:00
commit 1992cc0e41
4 changed files with 0 additions and 3081 deletions

View file

@ -1,137 +0,0 @@
/*
* drivers/serial/rk2818_serial.h
*
* Copyright (C) 2010 ROCKCHIP, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* 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 __DRIVERS_SERIAL_RK2818_SERIAL_H
#define __DRIVERS_SERIAL_RK2818_SERIAL_H
#define UART_RBR 0x0000 /* Receive Buffer Register */
#define UART_THR 0x0000 /* Transmit Holding Register */
#define UART_DLL 0x0000 /* Divisor Latch (Low) */
#define UART_DLH 0x0004 /* Divisor Latch (High) */
#define UART_IER 0x0004 /* Interrupt Enable Register */
#define UART_IIR 0x0008 /* Interrupt Identification Register */
#define UART_FCR 0x0008 /* FIFO Control Register */
#define UART_LCR 0x000C /* Line Control Register */
#define UART_MCR 0x0010 /* Modem Control Register */
#define UART_LSR 0x0014 /* [0x0000_0060] Line Status Register */
#define UART_MSR 0x0018 /* Modem Status Register */
#define UART_SCR 0x001c /* Scratchpad Register */
#define UART_SRBR(n) (0x0030+((n) * 4)) /* Shadow Receive Buffer Register */
#define UART_STHR(n) (0x0030+((n) * 4)) /* Shadow Transmit Holding Register */
#define UART_FAR 0x0070 /* FIFO Access Register */
#define UART_TFR 0x0074 /* Transmit FIFO Read */
#define UART_RFW 0x0078 /* Receive FIFO Write */
#define UART_USR 0x007C /* UART Status Register */
#define UART_TFL 0x0080 /* Transmit FIFO Level */
#define UART_RFL 0x0084 /* Receive FIFO Level */
#define UART_SRR 0x0088 /* Software Reset Register */
#define UART_SRTS 0x008C /* Shadow Request to Send */
#define UART_SBCR 0x0090 /* Shadow Break Control Register */
#define UART_SDMAM 0x0094 /* Shadow DMA Mode */
#define UART_SFE 0x0098 /* Shadow FIFO Enable */
#define UART_SRT 0x009C /* Shadow RCVR Trigger */
#define UART_STET 0x00A0 /* Shadow TX Empty Trigger */
#define UART_HTX 0x00A4 /* Halt TX */
#define UART_DMASA 0x00A8 /* DMA Software Acknowledge */
#define UART_CPR 0x00F4 /* Component Parameter Register */
#define UART_UCV 0x00F8 /* [0x3330_372a] UART Component Version */
#define UART_CTR 0x00FC /* [0x4457_0110] Component Type Register */
//#define UART_FCR 0x08
#define UART_FCR_FIFO_ENABLE (1<<0)
#define UART_FCR_CLEAR_RCVR (1<<1) /* Clear the RCVR FIFO */
#define UART_FCR_CLEAR_XMIT (1<<2) /* Clear the XMIT FIFO */
#define UART_FCR_DMA_SELECT (1<<3) /* For DMA applications */
#define UART_FCR_R_TRIG_00 0x00
#define UART_FCR_R_TRIG_01 0x40
#define UART_FCR_R_TRIG_10 0x80
#define UART_FCR_R_TRIG_11 0xc0
#define UART_FCR_T_TRIG_00 0x00
#define UART_FCR_T_TRIG_01 0x10
#define UART_FCR_T_TRIG_10 0x20
#define UART_FCR_T_TRIG_11 0x30
//#define UART_LCR 0x0c
#define LCR_DLA_EN (1<<7)
#define BREAK_CONTROL_BIT (1<<6)
#define EVEN_PARITY_SELECT (1<<4)
#define EVEN_PARITY (1<<4)
#define ODD_PARITY (0)
#define PARITY_DISABLED (0)
#define PARITY_ENABLED (1<<3)
#define ONE_STOP_BIT (0)
#define ONE_HALF_OR_TWO_BIT (1<<2)
#define LCR_WLS_5 (0x00)
#define LCR_WLS_6 (0x01)
#define LCR_WLS_7 (0x02)
#define LCR_WLS_8 (0x03)
#define UART_DATABIT_MASK (0x03)
/* Detail UART_IER Register Description */
#define UART_IER_THRE_MODE_INT_ENABLE 1<<7
#define UART_IER_MODEM_STATUS_INT_ENABLE 1<<3
#define UART_IER_RECV_LINE_STATUS_INT_ENABLE 1<<2
#define UART_IER_SEND_EMPTY_INT_ENABLE 1<<1
#define UART_IER_RECV_DATA_AVAIL_INT_ENABLE 1<<0
/* Detail UART_IIR Register Description */
#define UART_IIR_FIFO_DISABLE 0x00
#define UART_IIR_FIFO_ENABLE 0x03
#define UART_IIR_INT_ID_MASK 0x0F
#define UART_IIR_MODEM_STATUS 0x00
#define UART_IIR_NO_INTERRUPT_PENDING 0x01
#define UART_IIR_THR_EMPTY 0x02
#define UART_IIR_RECV_AVAILABLE 0x04
#define UART_IIR_RECV_LINE_STATUS 0x06
#define UART_IIR_BUSY_DETECT 0x07
#define UART_IIR_CHAR_TIMEOUT 0x0C
//#define UART_MCR 0x10
/* Modem Control Register */
#define UART_SIR_ENABLE (1 << 6)
#define UART_MCR_AFCEN (1 << 5) /* Auto Flow Control Mode enabled */
#define UART_MCR_URLB (1 << 4) /* Loop-back mode */
#define UART_MCR_UROUT2 (1 << 3) /* OUT2 signal */
#define UART_MCR_UROUT1 (1 << 2) /* OUT1 signal */
#define UART_MCR_URRTS (1 << 1) /* Request to Send */
#define UART_MCR_URDTR (1 << 0) /* Data Terminal Ready */
//#define UART_MSR 0x18
/* Modem Status Register */
#define UART_MSR_URDCD (1 << 7) /* Data Carrier Detect */
#define UART_MSR_URRI (1 << 6) /* Ring Indicator */
#define UART_MSR_URDSR (1 << 5) /* Data Set Ready */
#define UART_MSR_URCTS (1 << 4) /* Clear to Send */
#define UART_MSR_URDDCD (1 << 3) /* Delta Data Carrier Detect */
#define UART_MSR_URTERI (1 << 2) /* Trailing Edge Ring Indicator */
#define UART_MSR_URDDST (1 << 1) /* Delta Data Set Ready */
#define UART_MSR_URDCTS (1 << 0) /* Delta Clear to Send */
/* Detail UART_USR Register Description */
#define UART_RECEIVE_FIFO_FULL (1<<4)
#define UART_RECEIVE_FIFO_NOT_FULL (0)
#define UART_RECEIVE_FIFO_EMPTY (0)
#define UART_RECEIVE_FIFO_NOT_EMPTY (1<<3)
#define UART_TRANSMIT_FIFO_NOT_EMPTY (0)
#define UART_TRANSMIT_FIFO_EMPTY (1<<2)
#define UART_TRANSMIT_FIFO_FULL (0)
#define UART_TRANSMIT_FIFO_NOT_FULL (1<<1)
#define UART_USR_BUSY (1)
/*UART_LSR Line Status Register*/
#define UART_BREAK_INT_BIT (1<<4)/*break Interrupt bit*/
#endif /* __DRIVERS_SERIAL_RK2818_SERIAL_H */

File diff suppressed because it is too large Load diff

View file

@ -1,692 +0,0 @@
/*
*
* Copyright (C) 2010 liuyixing <lyx@rock-chips.com>
*
*
* Example platform data:
static struct plat_sc8800 sc8800_plat_data = {
.slav_rts_pin = RK29_PIN4_PD0,
.slav_rdy_pin = RK29_PIN4_PD0,
.master_rts_pin = RK29_PIN4_PD0,
.master_rdy_pin = RK29_PIN4_PD0,
//.poll_time = 100,
};
static struct spi_board_info spi_board_info[] = {
{
.modalias = "sc8800",
.platform_data = &sc8800_plat_data,
.max_speed_hz = 12*1000*1000,
.chip_select = 0,
},
};
* The initial minor number is 209 in the low-density serial port:
* mknod /dev/ttySPI0 c 204 209
*/
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
#include <linux/spi/spi.h>
#include <linux/freezer.h>
#include <linux/gpio.h>
#include "sc8800.h"
struct sc8800_port {
struct uart_port port;
struct spi_device *spi;
int cts; /* last CTS received for flow ctrl */
int tx_empty; /* last TX empty bit */
spinlock_t conf_lock; /* shared data */
int conf; /* configuration for the SC88000
* (bits 0-7, bits 8-11 are irqs) */
int rx_enabled; /* if we should rx chars */
int irq; /* irq assigned to the sc8800 */
int minor; /* minor number */
int loopback; /* 1 if we are in loopback mode */
/* for handling irqs: need workqueue since we do spi_sync */
struct workqueue_struct *workqueue;
struct work_struct work;
/* set to 1 to make the workhandler exit as soon as possible */
int force_end_work;
/* need to know we are suspending to avoid deadlock on workqueue */
int suspending;
/* hook for suspending SC8800 via dedicated pin */
void (*sc8800_hw_suspend) (int suspend);
/* poll time (in ms) for ctrl lines */
int poll_time;
/* and its timer */
struct timer_list timer;
/*signal define, always gpio*/
int slav_rts;
int slav_rdy;
int master_rts;
int master_rdy;
};
#define SC8800_MAJOR 204
#define SC8800_MINOR 209
#define MAX_SC8800 1
#define SPI_MAX_PACKET (8192-128)
#define FREAM_SIZE 64
#define SPI_DMA_SIZE PAGE_SIZE
void * g_dma_buffer = NULL;
dma_addr_t g_dma_addr;
#if 1
#define sc8800_dbg(x...) printk(x)
#else
#define sc8800_dbg(x...)
#endif
static struct sc8800_port *sc8800s[MAX_SC8800]; /* the chips */
static DEFINE_MUTEX(sc8800s_lock); /* race on probe */
static int sc8800_get_slave_rts_status(struct sc8800_port *s)
{
return gpio_get_value(s->slav_rts);
}
static int sc8800_get_slave_rdy_status(struct sc8800_port *s)
{
return gpio_get_value(s->slav_rdy);
}
static void sc8800_set_master_rts_status(struct sc8800_port *s, int value)
{
gpio_set_value(s->master_rts, value);
}
static void sc8800_set_master_rdy_status(struct sc8800_port *s, int value)
{
gpio_set_value(s->master_rdy, value);
}
static int sc8800_send_head_data(struct sc8800_port *s, u32 data_len)
{
char head[64] = {0};
struct spi_message message;
int status;
struct spi_transfer tran;
head[0] = 0x7f;
head[1] = 0x7e;
head[2] = 0x55;
head[3] = 0xaa;
head[4] = data_len & 0xff;
head[5] = (data_len>>8) & 0xff;
head[6] = (data_len>>16) & 0xff;
head[7] = (data_len>>24) & 0xff;
tran.tx_buf = (void *)(head);
tran.len = FREAM_SIZE;
spi_message_init(&message);
spi_message_add_tail(&tran, &message);
status = spi_sync(s->spi, &message);
if (status) {
dev_warn(&s->spi->dev, "error while calling spi_sync\n");
return -EIO;
}
return 0;
}
static int sc8800_recv_and_parse_head_data(struct sc8800_port *s, u32 *len)
{
struct spi_message message;
int status;
struct spi_transfer tran;
char buf[64] = {0};
u32 data_len = 0;
tran.rx_buf = (void *)buf;
tran.len = FREAM_SIZE;
spi_message_init(&message);
spi_message_add_tail(&tran, &message);
status = spi_sync(s->spi, &message);
if (status) {
dev_warn(&s->spi->dev, "error while calling spi_sync\n");
return -EIO;
}
if ((buf[0]!=0x7f) || (buf[1]!=0x7e) || (buf[2]!=0x55) || (buf[3]!=0xaa)) {
dev_warn(&s->spi->dev, "line %d, error head data", __LINE__);
return -EIO;
}
data_len = buf[5] + (buf[6]<<8) + (buf[7]<<16) + (buf[8]<<24);
*len = data_len;
sc8800_dbg("line %d, %d data need to read\n", __LINE__, *len);
return 0;
}
static int sc8800_send_data(struct sc8800_port *s, char *buf, int len)
{
#if 1
int status;
struct spi_message message;
struct spi_transfer tran;
tran.tx_buf = (void *)buf;
tran.len = len;
spi_message_init(&message);
spi_message_add_tail(&tran, &message);
status = spi_sync(s->spi, &message);
if (status) {
dev_warn(&s->spi->dev, "error while calling spi_sync\n");
return -EIO;
}
#else
int status;
struct spi_message message;
struct spi_transfer tran;
spi_message_init(&message);
if (!g_dma_buffer) {
g_dma_buffer = dma_alloc_coherent(NULL, SPI_DMA_SIZE, &g_dma_addr, GFP_KERNEL | GFP_DMA);
if (!g_dma_buffer) {
dev_err(&s->spi->dev, "alloc dma memory fail\n");
}
}
if (!g_dma_buffer) { //nomal
sc8800_dbg("send data nomal");
tran.tx_buf = (void *)buf;
tran.len = len;
}
else { //dma
//message.is_dma_mapped = 1;
//memcpy(g_dma_buffer, buf, );
}
spi_message_add_tail(&tran, &message);
status = spi_sync(s->spi, &message);
if (status) {
dev_warn(&s->spi->dev, "error while calling spi_sync\n");
return -EIO;
}
#endif
return 0;
}
static int sc8800_recv_data(struct sc8800_port *s, char *buf, int len)
{
struct spi_message message;
int status;
struct spi_transfer tran;
tran.rx_buf = (void *)buf;
tran.len = len;
spi_message_init(&message);
spi_message_add_tail(&tran, &message);
status = spi_sync(s->spi, &message);
if (status) {
dev_warn(&s->spi->dev, "error while calling spi_sync\n");
return -EIO;
}
return 0;
}
static void sc8800_work(struct work_struct *w);
static void sc8800_dowork(struct sc8800_port *s)
{
if (!s->force_end_work && !work_pending(&s->work) &&
!freezing(current) && !s->suspending)
queue_work(s->workqueue, &s->work);
}
static void sc8800_timeout(unsigned long data)
{
struct sc8800_port *s = (struct sc8800_port *)data;
if (s->port.state) {
sc8800_dowork(s);
mod_timer(&s->timer, jiffies + s->poll_time);
}
}
static void sc8800_work(struct work_struct *w)
{
struct sc8800_port *s = container_of(w, struct sc8800_port, work);
struct circ_buf *xmit = &s->port.state->xmit;
u32 len,i;
char *buf = NULL;
unsigned char ch;
dev_dbg(&s->spi->dev, "%s\n", __func__);
if (sc8800_get_slave_rts_status(s) == GPIO_HIGH) { //do wirte, master--->slave
if (sc8800_get_slave_rdy_status(s) == GPIO_HIGH) { /*1.check slave rdy, must be high*/
if (!(uart_circ_empty(xmit))) {
len = uart_circ_chars_pending(xmit);
len = (len > SPI_MAX_PACKET) ? SPI_MAX_PACKET : len;
sc8800_dbg("send data length = %d\n", len);
sc8800_set_master_rts_status(s, GPIO_LOW); /*2.set master rts low*/
sc8800_send_head_data(s,len); /*3.send 64byte head data*/
while (sc8800_get_slave_rdy_status(s)) { /*4.check slav rdy, wait for low */
msleep(1);
}
/*5.long data transmit*/
sc8800_send_data(s, xmit->buf+xmit->tail, len);
while(sc8800_get_slave_rdy_status(s)==GPIO_LOW) { /*6.wait for slave rdy high*/
msleep(1);
}
sc8800_set_master_rts_status(s, GPIO_HIGH); /*end transmit, set master rts high*/
xmit->tail = (xmit->tail + len) & (UART_XMIT_SIZE - 1);
s->port.icount.tx += len;
}
}
else { //slave not ready, do it next time
queue_work(s->workqueue, &s->work);
}
}
else { //do read, slave--->master
sc8800_set_master_rdy_status(s, GPIO_LOW);
sc8800_recv_and_parse_head_data(s, &len);
buf = (char *)kzalloc(len, GFP_KERNEL);
if (!buf) {
dev_err(&s->spi->dev, "line %d, err while malloc mem\n", __LINE__);
sc8800_set_master_rdy_status(s, GPIO_HIGH);
return ;
}
memset(buf, 0, len);
sc8800_recv_data(s, buf, len);
while (sc8800_get_slave_rts_status(s) == GPIO_LOW) {
msleep(1);
}
sc8800_set_master_rdy_status(s, GPIO_HIGH);
for (i=0; i<len; i++) {
ch = buf[i];
uart_insert_char(&s->port, 0, 0, ch, TTY_NORMAL);
}
tty_flip_buffer_push(s->port.state->port.tty);
}
}
static irqreturn_t sc8800_irq(int irqno, void *dev_id)
{
struct sc8800_port *s = dev_id;
dev_dbg(&s->spi->dev, "%s\n", __func__);
sc8800_dowork(s);
return IRQ_HANDLED;
}
static void sc8800_enable_ms(struct uart_port *port)
{
struct sc8800_port *s = container_of(port,
struct sc8800_port,
port);
if (s->poll_time > 0)
mod_timer(&s->timer, jiffies);
dev_dbg(&s->spi->dev, "%s\n", __func__);
}
static void sc8800_start_tx(struct uart_port *port)
{
struct sc8800_port *s = container_of(port,
struct sc8800_port,
port);
dev_dbg(&s->spi->dev, "%s\n", __func__);
sc8800_dowork(s);
}
static void sc8800_stop_rx(struct uart_port *port)
{
struct sc8800_port *s = container_of(port,
struct sc8800_port,
port);
dev_dbg(&s->spi->dev, "%s\n", __func__);
s->rx_enabled = 0;
sc8800_dowork(s);
}
static void sc8800_shutdown(struct uart_port *port)
{
struct sc8800_port *s = container_of(port,
struct sc8800_port,
port);
dev_dbg(&s->spi->dev, "%s\n", __func__);
if (s->suspending)
return;
s->force_end_work = 1;
if (s->poll_time > 0)
del_timer_sync(&s->timer);
if (s->workqueue) {
flush_workqueue(s->workqueue);
destroy_workqueue(s->workqueue);
s->workqueue = NULL;
}
if (s->irq)
free_irq(s->irq, s);
gpio_free(s->master_rdy);
gpio_free(s->master_rts);
gpio_free(s->slav_rdy);
gpio_free(s->slav_rts);
/* set shutdown mode to save power */
if (s->sc8800_hw_suspend)
s->sc8800_hw_suspend(1);
}
static int sc8800_startup(struct uart_port *port)
{
struct sc8800_port *s = container_of(port,
struct sc8800_port,
port);
int ret;
char b[12];
dev_dbg(&s->spi->dev, "%s\n", __func__);
s->rx_enabled = 1;
if (s->suspending)
return 0;
s->force_end_work = 0;
sprintf(b, "sc8800-%d", s->minor);
s->workqueue = create_freezeable_workqueue(b);
if (!s->workqueue) {
dev_warn(&s->spi->dev, "cannot create workqueue\n");
return -EBUSY;
}
INIT_WORK(&s->work, sc8800_work);
ret = gpio_request(s->slav_rts, "slav rts");
if (ret) {
dev_err(&s->spi->dev, "line %d: gpio request err\n", __LINE__);
ret = -EBUSY;
goto gpio_err1;
}
ret = gpio_request(s->slav_rdy, "slav rdy");
if (ret) {
dev_err(&s->spi->dev, "line %d: gpio request err\n", __LINE__);
ret = -EBUSY;
goto gpio_err2;
}
ret = gpio_request(s->master_rts, "master rts");
if (ret) {
dev_err(&s->spi->dev, "line %d: gpio request err\n", __LINE__);
ret = -EBUSY;
goto gpio_err3;
}
ret = gpio_request(s->master_rdy, "master rdy");
if (ret) {
dev_err(&s->spi->dev, "line %d: gpio request err\n", __LINE__);
ret = -EBUSY;
goto gpio_err4;
}
gpio_direction_input(s->slav_rts);
gpio_pull_updown(s->slav_rts, GPIOPullUp);
gpio_direction_input(s->slav_rdy);
gpio_pull_updown(s->slav_rdy, GPIOPullUp);
gpio_direction_output(s->master_rts, GPIO_HIGH);
gpio_direction_output(s->master_rdy, GPIO_HIGH);
if (request_irq(s->irq, sc8800_irq,
IRQF_TRIGGER_FALLING, "sc8800", s) < 0) {
dev_warn(&s->spi->dev, "cannot allocate irq %d\n", s->irq);
s->irq = 0;
goto irq_err;
}
if (s->sc8800_hw_suspend)
s->sc8800_hw_suspend(0);
sc8800_dowork(s);
sc8800_enable_ms(&s->port);
return 0;
irq_err:
gpio_free(s->master_rdy);
gpio_err4:
gpio_free(s->master_rts);
gpio_err3:
gpio_free(s->slav_rdy);
gpio_err2:
gpio_free(s->slav_rts);
gpio_err1:
destroy_workqueue(s->workqueue);
s->workqueue = NULL;
return ret;
}
static struct uart_ops sc8800_ops = {
.start_tx = sc8800_start_tx,
.stop_rx = sc8800_stop_rx,
.startup = sc8800_startup,
.shutdown = sc8800_shutdown,
};
static struct uart_driver sc8800_uart_driver = {
.owner = THIS_MODULE,
.driver_name = "ttySPI",
.dev_name = "ttySPI",
.major = SC8800_MAJOR,
.minor = SC8800_MINOR,
.nr = MAX_SC8800,
};
static int uart_driver_registered;
static int __devinit sc8800_probe(struct spi_device *spi)
{
int i, retval;
struct plat_sc8800 *pdata;
mutex_lock(&sc8800s_lock);
if (!uart_driver_registered) {
uart_driver_registered = 1;
retval = uart_register_driver(&sc8800_uart_driver);
if (retval) {
printk(KERN_ERR "Couldn't register sc8800 uart driver\n");
mutex_unlock(&sc8800s_lock);
return retval;
}
}
for (i = 0; i < MAX_SC8800; i++)
if (!sc8800s[i])
break;
if (i == MAX_SC8800) {
dev_warn(&spi->dev, "too many SC8800 chips\n");
mutex_unlock(&sc8800s_lock);
return -ENOMEM;
}
sc8800s[i] = kzalloc(sizeof(struct sc8800_port), GFP_KERNEL);
if (!sc8800s[i]) {
dev_warn(&spi->dev,
"kmalloc for sc8800 structure %d failed!\n", i);
mutex_unlock(&sc8800s_lock);
return -ENOMEM;
}
sc8800s[i]->spi = spi;
spin_lock_init(&sc8800s[i]->conf_lock);
dev_set_drvdata(&spi->dev, sc8800s[i]);
pdata = spi->dev.platform_data;
sc8800s[i]->irq = gpio_to_irq(pdata->slav_rts_pin);
sc8800s[i]->slav_rts = pdata->slav_rts_pin;
sc8800s[i]->slav_rdy = pdata->slav_rdy_pin;
sc8800s[i]->master_rts = pdata->master_rts_pin;
sc8800s[i]->master_rdy = pdata->master_rdy_pin;
//sc8800s[i]->sc8800_hw_suspend = pdata->sc8800_hw_suspend;
sc8800s[i]->minor = i;
init_timer(&sc8800s[i]->timer);
sc8800s[i]->timer.function = sc8800_timeout;
sc8800s[i]->timer.data = (unsigned long) sc8800s[i];
dev_dbg(&spi->dev, "%s: adding port %d\n", __func__, i);
sc8800s[i]->port.irq = sc8800s[i]->irq;
sc8800s[i]->port.uartclk = 24000000;
sc8800s[i]->port.fifosize = 64;
sc8800s[i]->port.ops = &sc8800_ops;
sc8800s[i]->port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
sc8800s[i]->port.line = i;
sc8800s[i]->port.dev = &spi->dev;
retval = uart_add_one_port(&sc8800_uart_driver, &sc8800s[i]->port);
if (retval < 0)
dev_warn(&spi->dev,
"uart_add_one_port failed for line %d with error %d\n",
i, retval);
/* set shutdown mode to save power. Will be woken-up on open */
if (sc8800s[i]->sc8800_hw_suspend)
sc8800s[i]->sc8800_hw_suspend(1);
mutex_unlock(&sc8800s_lock);
return 0;
}
static int __devexit sc8800_remove(struct spi_device *spi)
{
struct sc8800_port *s = dev_get_drvdata(&spi->dev);
int i;
mutex_lock(&sc8800s_lock);
/* find out the index for the chip we are removing */
for (i = 0; i < MAX_SC8800; i++)
if (sc8800s[i] == s)
break;
dev_dbg(&spi->dev, "%s: removing port %d\n", __func__, i);
uart_remove_one_port(&sc8800_uart_driver, &sc8800s[i]->port);
kfree(sc8800s[i]);
sc8800s[i] = NULL;
/* check if this is the last chip we have */
for (i = 0; i < MAX_SC8800; i++)
if (sc8800s[i]) {
mutex_unlock(&sc8800s_lock);
return 0;
}
pr_debug("removing sc8800 driver\n");
uart_unregister_driver(&sc8800_uart_driver);
mutex_unlock(&sc8800s_lock);
return 0;
}
#ifdef CONFIG_PM
static int sc8800_suspend(struct spi_device *spi, pm_message_t state)
{
struct sc8800_port *s = dev_get_drvdata(&spi->dev);
dev_dbg(&s->spi->dev, "%s\n", __func__);
disable_irq(s->irq);
s->suspending = 1;
uart_suspend_port(&sc8800_uart_driver, &s->port);
if (s->sc8800_hw_suspend)
s->sc8800_hw_suspend(1);
return 0;
}
static int sc8800_resume(struct spi_device *spi)
{
struct sc8800_port *s = dev_get_drvdata(&spi->dev);
dev_dbg(&s->spi->dev, "%s\n", __func__);
if (s->sc8800_hw_suspend)
s->sc8800_hw_suspend(0);
uart_resume_port(&sc8800_uart_driver, &s->port);
s->suspending = 0;
enable_irq(s->irq);
if (s->workqueue)
sc8800_dowork(s);
return 0;
}
#else
#define sc8800_suspend NULL
#define sc8800_resume NULL
#endif
static struct spi_driver sc8800_driver = {
.driver = {
.name = "sc8800",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = sc8800_probe,
.remove = __devexit_p(sc8800_remove),
.suspend = sc8800_suspend,
.resume = sc8800_resume,
};
static int __init sc8800_init(void)
{
return spi_register_driver(&sc8800_driver);
}
module_init(sc8800_init);
static void __exit sc8800_exit(void)
{
spi_unregister_driver(&sc8800_driver);
}
module_exit(sc8800_exit);
MODULE_DESCRIPTION("SC8800 driver");
MODULE_AUTHOR("liuyixing <lyx@rock-chips.com>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("spi:SC8800");

View file

@ -1,24 +0,0 @@
#ifndef __SC8800_H__
#define __SC8800_H__
typedef struct _spi_packet_head {
u16 tag; //HEADER_TAG(0x7e7f)
u16 type; //HEADER_TYPE(0xaa55)
u32 length; //the length of data after head (8192-128 bytes)
u32 frame_num; //no used , always 0
u32 reserved2; //reserved
} SPI_PACKET_HEAD_T;
/*define flatform data struct*/
struct plat_sc8800 {
int slav_rts_pin;
int slav_rdy_pin;
int master_rts_pin;
int master_rdy_pin;
int poll_time;
int (*io_init)(void);
int (*io_deinit)(void);
};
#endif