This repository has been archived on 2025-06-06. You can view files and clone it, but cannot push or open issues or pull requests.
Files
android-g900/kernel-2.6.33/arch/arm/mach-pxa/g900/msm6280/msm6280_tty_data.c
2011-04-04 23:17:39 +06:00

240 lines
5.8 KiB
C
Executable File
Raw Blame History

/*
*
* 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);
}