Line 97... |
Line 97... |
if(!(uart->regs.ier & UART_IER_MSI))
|
if(!(uart->regs.ier & UART_IER_MSI))
|
return;
|
return;
|
|
|
if((uart->regs.iir & UART_IIR_NO_INT) || (uart->regs.iir == UART_IIR_MSI)) {
|
if((uart->regs.iir & UART_IIR_NO_INT) || (uart->regs.iir == UART_IIR_MSI)) {
|
TRACE("Raiseing modem status interrupt\n");
|
TRACE("Raiseing modem status interrupt\n");
|
uart_clear_int(uart, uart->regs.iir);
|
|
|
|
|
if((uart->regs.iir != UART_IIR_MSI) && (uart->regs.iir != UART_IIR_NO_INT)) {
|
|
uart_clear_int(uart, uart->regs.iir);
|
|
uart->regs.iir = UART_IIR_MSI;
|
|
} else {
|
uart->regs.iir = UART_IIR_MSI;
|
uart->regs.iir = UART_IIR_MSI;
|
SCHED_ADD(uart_int_msi, dat, UART_CLOCK_DIVIDER);
|
SCHED_ADD(uart_int_msi, dat, UART_CLOCK_DIVIDER);
|
report_interrupt(uart->irq);
|
report_interrupt(uart->irq);
|
}
|
}
|
}
|
}
|
|
}
|
|
|
static void uart_int_thri(void *dat)
|
static void uart_int_thri(void *dat)
|
{
|
{
|
struct dev_16450 *uart = dat;
|
struct dev_16450 *uart = dat;
|
|
|
Line 117... |
Line 121... |
return;
|
return;
|
|
|
if((uart->regs.iir & UART_IIR_NO_INT) || (uart->regs.iir == UART_IIR_MSI) ||
|
if((uart->regs.iir & UART_IIR_NO_INT) || (uart->regs.iir == UART_IIR_MSI) ||
|
(uart->regs.iir == UART_IIR_THRI)) {
|
(uart->regs.iir == UART_IIR_THRI)) {
|
TRACE("Raiseing transmitter holding register interrupt\n");
|
TRACE("Raiseing transmitter holding register interrupt\n");
|
uart_clear_int(uart, uart->regs.iir);
|
|
|
|
|
if((uart->regs.iir != UART_IIR_THRI) && (uart->regs.iir != UART_IIR_NO_INT)) {
|
|
uart_clear_int(uart, uart->regs.iir);
|
|
uart->regs.iir = UART_IIR_THRI;
|
|
} else {
|
uart->regs.iir = UART_IIR_THRI;
|
uart->regs.iir = UART_IIR_THRI;
|
SCHED_ADD(uart_int_thri, dat, UART_CLOCK_DIVIDER);
|
SCHED_ADD(uart_int_thri, dat, UART_CLOCK_DIVIDER);
|
report_interrupt(uart->irq);
|
report_interrupt(uart->irq);
|
}
|
}
|
}
|
}
|
|
}
|
|
|
static void uart_int_cti(void *dat)
|
static void uart_int_cti(void *dat)
|
{
|
{
|
struct dev_16450 *uart = dat;
|
struct dev_16450 *uart = dat;
|
|
|
Line 136... |
Line 144... |
if(!(uart->regs.ier & UART_IER_RDI))
|
if(!(uart->regs.ier & UART_IER_RDI))
|
return;
|
return;
|
|
|
if((uart->regs.iir != UART_IIR_RLSI) && (uart->regs.iir != UART_IIR_RDI)) {
|
if((uart->regs.iir != UART_IIR_RLSI) && (uart->regs.iir != UART_IIR_RDI)) {
|
TRACE("Raiseing character timeout interrupt\n");
|
TRACE("Raiseing character timeout interrupt\n");
|
uart_clear_int(uart, uart->regs.iir);
|
|
|
|
|
if((uart->regs.iir != UART_IIR_CTI) && (uart->regs.iir != UART_IIR_NO_INT)) {
|
|
uart_clear_int(uart, uart->regs.iir);
|
|
uart->regs.iir = UART_IIR_CTI;
|
|
} else {
|
uart->regs.iir = UART_IIR_CTI;
|
uart->regs.iir = UART_IIR_CTI;
|
SCHED_ADD(uart_int_cti, dat, UART_CLOCK_DIVIDER);
|
SCHED_ADD(uart_int_cti, dat, UART_CLOCK_DIVIDER);
|
report_interrupt(uart->irq);
|
report_interrupt(uart->irq);
|
}
|
}
|
}
|
}
|
|
}
|
|
|
static void uart_int_rdi(void *dat)
|
static void uart_int_rdi(void *dat)
|
{
|
{
|
struct dev_16450 *uart = dat;
|
struct dev_16450 *uart = dat;
|
|
|
Line 155... |
Line 167... |
if(!(uart->regs.ier & UART_IER_RDI))
|
if(!(uart->regs.ier & UART_IER_RDI))
|
return;
|
return;
|
|
|
if(uart->regs.iir != UART_IIR_RLSI) {
|
if(uart->regs.iir != UART_IIR_RLSI) {
|
TRACE("Raiseing receiver data interrupt\n");
|
TRACE("Raiseing receiver data interrupt\n");
|
uart_clear_int(uart, uart->regs.iir);
|
|
|
|
|
if((uart->regs.iir != UART_IIR_RDI) && (uart->regs.iir != UART_IIR_NO_INT)) {
|
|
uart_clear_int(uart, uart->regs.iir);
|
|
uart->regs.iir = UART_IIR_RDI;
|
|
} else {
|
uart->regs.iir = UART_IIR_RDI;
|
uart->regs.iir = UART_IIR_RDI;
|
SCHED_ADD(uart_int_rdi, dat, UART_CLOCK_DIVIDER);
|
SCHED_ADD(uart_int_rdi, dat, UART_CLOCK_DIVIDER);
|
report_interrupt(uart->irq);
|
report_interrupt(uart->irq);
|
}
|
}
|
}
|
}
|
|
}
|
|
|
static void uart_int_rlsi(void *dat)
|
static void uart_int_rlsi(void *dat)
|
{
|
{
|
struct dev_16450 *uart = dat;
|
struct dev_16450 *uart = dat;
|
|
|
uart->istat.ints |= 1 << UART_IIR_RLSI;
|
uart->istat.ints |= 1 << UART_IIR_RLSI;
|
|
|
if(!(uart->regs.ier & UART_IER_RLSI))
|
if(!(uart->regs.ier & UART_IER_RLSI))
|
return;
|
return;
|
|
|
uart_clear_int(uart, uart->regs.iir);
|
|
|
|
TRACE("Raiseing receiver line status interrupt\n");
|
TRACE("Raiseing receiver line status interrupt\n");
|
|
|
/* Highest priority interrupt */
|
/* Highest priority interrupt */
|
|
if((uart->regs.iir != UART_IIR_RLSI) && (uart->regs.iir != UART_IIR_NO_INT)) {
|
|
uart_clear_int(uart, uart->regs.iir);
|
|
uart->regs.iir = UART_IIR_RLSI;
|
|
} else {
|
uart->regs.iir = UART_IIR_RLSI;
|
uart->regs.iir = UART_IIR_RLSI;
|
SCHED_ADD(uart_int_rlsi, dat, UART_CLOCK_DIVIDER);
|
SCHED_ADD(uart_int_rlsi, dat, UART_CLOCK_DIVIDER);
|
report_interrupt(uart->irq);
|
report_interrupt(uart->irq);
|
}
|
}
|
|
}
|
|
|
/* Checks to see if an RLSI interrupt is due and schedules one if need be */
|
/* Checks to see if an RLSI interrupt is due and schedules one if need be */
|
static void uart_check_rlsi(void *dat)
|
static void uart_check_rlsi(void *dat)
|
{
|
{
|
struct dev_16450 *uart = dat;
|
struct dev_16450 *uart = dat;
|
Line 197... |
Line 216... |
/* Checks to see if an RDI interrupt is due and schedules one if need be */
|
/* Checks to see if an RDI interrupt is due and schedules one if need be */
|
static void uart_check_rdi(void *dat)
|
static void uart_check_rdi(void *dat)
|
{
|
{
|
struct dev_16450 *uart = dat;
|
struct dev_16450 *uart = dat;
|
|
|
if(uart->istat.rxbuf_full >= UART_FIFO_TRIGGER(uart->regs.fcr >> 6))
|
if(uart->istat.rxbuf_full >= UART_FIFO_TRIGGER(uart->regs.fcr >> 6)) {
|
|
TRACE("FIFO trigger level reached %i\n",
|
|
UART_FIFO_TRIGGER(uart->regs.fcr >> 6));
|
uart_int_rdi(uart);
|
uart_int_rdi(uart);
|
}
|
}
|
|
}
|
|
|
/* Raises the next highest priority interrupt */
|
/* Raises the next highest priority interrupt */
|
static void uart_next_int(void *dat)
|
static void uart_next_int(void *dat)
|
{
|
{
|
struct dev_16450 *uart = dat;
|
struct dev_16450 *uart = dat;
|
Line 231... |
Line 253... |
/* Clears potentially pending interrupts */
|
/* Clears potentially pending interrupts */
|
static void uart_clear_int(struct dev_16450 *uart, int intr)
|
static void uart_clear_int(struct dev_16450 *uart, int intr)
|
{
|
{
|
uart->istat.ints &= ~(1 << intr);
|
uart->istat.ints &= ~(1 << intr);
|
|
|
|
TRACE("Interrupt pending was %x\n", uart->regs.iir);
|
|
|
/* Short-circuit most likely case */
|
/* Short-circuit most likely case */
|
if(uart->regs.iir == UART_IIR_NO_INT)
|
if(uart->regs.iir == UART_IIR_NO_INT)
|
return;
|
return;
|
|
|
if(intr != uart->regs.iir)
|
if(intr != uart->regs.iir)
|
Line 580... |
Line 604... |
}
|
}
|
}
|
}
|
|
|
switch (addr) {
|
switch (addr) {
|
case UART_TXBUF:
|
case UART_TXBUF:
|
TRACE("Adding %"PRIx8" to TX FIFO\n", value);
|
TRACE("Adding %"PRIx8" to TX FIFO (fill %i)\n", value,
|
|
uart->istat.txbuf_full);
|
uart->regs.lsr &= ~UART_LSR_TXBUFE;
|
uart->regs.lsr &= ~UART_LSR_TXBUFE;
|
if (uart->istat.txbuf_full < uart->fifo_len) {
|
if (uart->istat.txbuf_full < uart->fifo_len) {
|
uart->regs.txbuf[uart->istat.txbuf_head] = value;
|
uart->regs.txbuf[uart->istat.txbuf_head] = value;
|
uart->istat.txbuf_head = (uart->istat.txbuf_head + 1) % uart->fifo_len;
|
uart->istat.txbuf_head = (uart->istat.txbuf_head + 1) % uart->fifo_len;
|
if(!uart->istat.txbuf_full++ && (uart->regs.lsr & UART_LSR_TXSERE))
|
if(!uart->istat.txbuf_full++ && (uart->regs.lsr & UART_LSR_TXSERE))
|