240 lines
5.8 KiB
C
Executable File
240 lines
5.8 KiB
C
Executable File
/*
|
||
*
|
||
* Based on arch/arm/mach-pxa/htcblueangel/blueangel_dpram.c
|
||
* Autor: Angell Fear <angell@angellfear.ru>
|
||
* MSM6280 to PXA270 communication on Dual Port RAM for Toshiba G900
|
||
*
|
||
*/
|
||
|
||
|
||
static void dpram_data_enable_ms(struct uart_port *port) {}
|
||
static void dpram_data_stop_tx(struct uart_port *port) {}
|
||
static void dpram_data_stop_rx(struct uart_port *port) {}
|
||
static unsigned int dpram_data_tx_empty(struct uart_port *port) { return TIOCSER_TEMT; }
|
||
static unsigned int dpram_data_get_mctrl(struct uart_port *port) { return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; }
|
||
static void dpram_data_set_mctrl(struct uart_port *port, unsigned int mctrl) {}
|
||
static void dpram_data_break_ctl(struct uart_port *port, int break_state) {}
|
||
static void dpram_data_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old){}
|
||
static void dpram_data_pm(struct uart_port *port, unsigned int state, unsigned int oldstate){}
|
||
static void dpram_data_release_port(struct uart_port *port){}
|
||
static int dpram_data_request_port(struct uart_port *port){ return 0; }
|
||
static void dpram_data_config_port(struct uart_port *port, int flags) { port->type = PORT_DPRAM;}
|
||
static int dpram_data_verify_port(struct uart_port *port, struct serial_struct *ser) { return -EINVAL;}
|
||
static const char * dpram_data_type(struct uart_port *port) { return "DPRAM"; }
|
||
|
||
|
||
|
||
/**/
|
||
|
||
static void
|
||
receive_chars_data(struct uart_port *up)
|
||
{
|
||
unsigned int ch,i=0;
|
||
u16 head,tail;
|
||
|
||
struct tty_struct *tty;
|
||
|
||
//if( msm6280_data.en_data ) ddvprintk("en_data = true\n"); else ddvprintk("en_data = false\n");
|
||
if( msm6280_data.en_data ) tty = up->state->port.tty;
|
||
|
||
ddbprintk("receive_chars_data\n");
|
||
|
||
head = *((u16*)msm6280_data.data_virt + RX_DT_START);
|
||
tail = *((u16*)msm6280_data.data_virt + RX_DT_START + 1);
|
||
ddvprintk("transmit_chars_data head = 0x%04x, tail = 0x%04x: \n",head,tail);
|
||
if(tail == head ) return ; // mb fast IRQ
|
||
ddprintk("DR<-: ");
|
||
|
||
while((head != tail))
|
||
{
|
||
if(tail >= RX_DT_BUF){
|
||
tail = 0x00;
|
||
}
|
||
if(i >= RX_DT_BUF) break;
|
||
|
||
ch =*((u8*)msm6280_data.data_virt+tail+(RX_DT_BUF_START));
|
||
tail++;
|
||
i++;
|
||
if (msm6280_data.en_data)
|
||
{
|
||
up->icount.rx++;
|
||
if (!uart_handle_sysrq_char(up, c))
|
||
{
|
||
tty_insert_flip_char(tty, ch, TTY_NORMAL);
|
||
|
||
}
|
||
}
|
||
dcharprint(ch);
|
||
|
||
|
||
}
|
||
|
||
if (msm6280_data.en_data) tty_flip_buffer_push(tty);
|
||
*((u16*)msm6280_data.data_virt+RX_DT_START + 1 ) = tail;
|
||
drprintk("\n");
|
||
return;
|
||
}
|
||
|
||
static unsigned char
|
||
transmit_char_data(struct uart_port *up, struct circ_buf *xmit)
|
||
{
|
||
unsigned char ret;
|
||
|
||
ret=xmit->buf[xmit->tail];
|
||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||
up->icount.tx++;
|
||
|
||
return ret;
|
||
}
|
||
|
||
static void transmit_chars_data(struct uart_port *up)
|
||
{
|
||
struct circ_buf *xmit = &up->state->xmit;
|
||
u16 count;
|
||
u16 head,tail;
|
||
char s;
|
||
|
||
if (up->x_char) {
|
||
|
||
ddprintk("send x_char 0x%02x(%c)\n",up->x_char,up->x_char);
|
||
up->icount.tx++;
|
||
up->x_char = 0;
|
||
return;
|
||
}
|
||
|
||
if (uart_circ_empty(xmit) || uart_tx_stopped(up)) {
|
||
dpram_data_stop_tx(up);
|
||
return;
|
||
}
|
||
ddbprintk("ransmit_chars_data\n");
|
||
|
||
/*************************/
|
||
head = *((u16*)msm6280_data.data_virt + TX_DT_START);
|
||
tail = *((u16*)msm6280_data.data_virt + TX_DT_START + 1);
|
||
|
||
count=TX_DT_BUF-1;
|
||
ddprintk("\nDS-> :");
|
||
while(count--)
|
||
{
|
||
//if(tail==(head+1)) {
|
||
// printk("FULL BUF0x%04x, tail = 0x%04x: \n",head,tail);
|
||
// break; // <20><><EFBFBD><EFBFBD><EFBFBD>, DPram <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
|
||
//}
|
||
if(head >= TX_DT_BUF){
|
||
head = 0x00;
|
||
}
|
||
s=transmit_char_data(up, xmit);
|
||
|
||
*((u8*)msm6280_data.data_virt+head+(TX_DT_BUF_START)) = s;
|
||
|
||
ddcharprint(s);
|
||
head++;
|
||
|
||
if (uart_circ_empty(xmit)) // <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20> uarte <20><><EFBFBD><EFBFBD><EFBFBD>
|
||
break;
|
||
|
||
}
|
||
*((u16*)msm6280_data.data_virt + TX_DT_START) = head;
|
||
MQBOX0 |= 0b100; // chanel 2
|
||
drprintk("\n");
|
||
|
||
/*************************/
|
||
|
||
|
||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||
uart_write_wakeup(up);
|
||
|
||
if (uart_circ_empty(xmit))
|
||
dpram_data_stop_tx(up);
|
||
}
|
||
|
||
static void dpram_data_start_tx(struct uart_port *port)
|
||
{
|
||
transmit_chars_data(port);
|
||
}
|
||
|
||
static int dpram_data_startup(struct uart_port *port)
|
||
{
|
||
if(!msm6280_data.en_data) msm6280_data.port_data = port;
|
||
msm6280_data.en_data = true;
|
||
receive_chars_data(msm6280_data.port_data);
|
||
return 0;
|
||
}
|
||
|
||
static void dpram_data_shutdown(struct uart_port *port)
|
||
{
|
||
msm6280_data.en_data = false;
|
||
}
|
||
|
||
|
||
struct uart_ops dpram_data_pops = {
|
||
.tx_empty = dpram_data_tx_empty,
|
||
.set_mctrl = dpram_data_set_mctrl,
|
||
.get_mctrl = dpram_data_get_mctrl,
|
||
.stop_tx = dpram_data_stop_tx,
|
||
.start_tx = dpram_data_start_tx,
|
||
.stop_rx = dpram_data_stop_rx,
|
||
.enable_ms = dpram_data_enable_ms,
|
||
.break_ctl = dpram_data_break_ctl,
|
||
.startup = dpram_data_startup,
|
||
.shutdown = dpram_data_shutdown,
|
||
.set_termios = dpram_data_set_termios,
|
||
.pm = dpram_data_pm,
|
||
.type = dpram_data_type,
|
||
.release_port = dpram_data_release_port,
|
||
.request_port = dpram_data_request_port,
|
||
.config_port = dpram_data_config_port,
|
||
.verify_port = dpram_data_verify_port,
|
||
};
|
||
|
||
static struct uart_port dpram_data_port = {
|
||
.type = PORT_DPRAM,
|
||
.iotype = UPIO_MEM,
|
||
.irq = -1/*IRQ_RX*/,
|
||
.uartclk = 115000 * 16,
|
||
.fifosize = 64,
|
||
.ops = &dpram_data_pops,
|
||
.line = 1,
|
||
};
|
||
|
||
static struct uart_driver dpram_data_reg_data = {
|
||
.owner = THIS_MODULE,
|
||
.driver_name = "msm6280_data_uart",
|
||
.dev_name = "ttyMSM",
|
||
//.dev_name = "smd",
|
||
.major = TTY_MAJOR,
|
||
.minor = 73,
|
||
.nr = 3,
|
||
};
|
||
|
||
|
||
int msm6280_tty_data_probe()
|
||
{
|
||
int ret;
|
||
|
||
ret = uart_register_driver(&dpram_data_reg_data);
|
||
if (ret != 0)
|
||
goto err1;
|
||
|
||
dpram_data_port.mapbase=msm6280_data.data_phys+RX_DT_START;
|
||
ret = uart_add_one_port(&dpram_data_reg_data, &dpram_data_port);
|
||
if (ret != 0)
|
||
goto err2;
|
||
return 0;
|
||
|
||
err2:
|
||
uart_remove_one_port(&dpram_data_reg_data, &dpram_data_port);
|
||
err1:
|
||
uart_unregister_driver(&dpram_data_reg_data);
|
||
return ret;
|
||
}
|
||
|
||
void msm6280_tty_data_remove(void)
|
||
{
|
||
uart_remove_one_port(&dpram_data_reg_data, &dpram_data_port);
|
||
uart_unregister_driver(&dpram_data_reg_data);
|
||
}
|
||
|
||
|
||
|