This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

OMAPL-138 (ARM side) UART0,1 Support under Linux

Other Parts Discussed in Thread: DA8XX

I have been doing some development using the OMAPL-138 Experimenter's kit and am now trying to get things set up for my own hardware.  My board will be different from the Experimenter's kit in that I will be using UART1 for the Linux console on the ARM rather than UART2.  I've run into a problem that seems to be related to the Linux driver for the UART.  In an attempt to set the console to use UART1 I ran across the following comment in .../arch/arm/mach-davinci/board-da850-evm.c  in function static __init void da850_evm_init(void)  :

/*
 * shut down uart 0 and 1; they are not used on the board and
 * accessing them causes endless "too much work in irq53" messages
 * with arago fs
*/

Sure enough, if I enable either UART0 or UART1 (with the console still set to UART2) I get an endless sequence of "Serial8250: too much work in irq53" messages on the console at the point in the boot process where I normally would see a login prompt.  I tried to disable UART2 and only enable UART1 and then monitored the UART1 TX data (3.3V levels) with a scope.  I looked at the cadence of serial messages on the UART1 console port and it appears that it goes through the Linux boot messages and about the time I should get a login prompt it starts constantly sending data which I assume is the same "too much work for irq53" message.

The error message comes from .../drivers/serial/8250.c in the function: static irqreturn_t serial8250_interrupt(int irq, void *dev_id).

Since there was a comment in the initialization code that references this issue it seems that it is a known issue but I have not been able to find a resolution.  If anyone can point me in the direction of a solution it would be greatly appreciated.

Best Regards,

--James Schaffer

  • Some additional information:

    I put some debug code in static irqreturn_t serial8250_interrupt(int irq, void *dev_id) in .../drivers/serial/8250.c to print out the value of the IIR register in the UART when this routine is called.  It seems that the value of the IIR register is always 0xC0 when the interrupt is serviced.  According to the IIR description in sprufm6b.pdf (UART user's guide) this is not a valid value.  The '0' in bit 0 (IPEND) indicates that an interrupt is pending but the '000' in bits 3-1 (INTID) is a reserved value.  Also printed out the LSR value and it reads 0x60 (Transmitter empty - TEMT and Transmitter holding register empty - THRE asserted).

     

    --James

  • James,

    When IIR[3:0] = 0, something in the Modem Status Register initiated the interrupt.

    -Tommy

  • Thanks.  That appears to be exactly what is happening.  Since UART1 CTS is pinmuxed with AHCLKX and the experimenter's kit uses the AHCLKX input it looks like the CTS input is receiving the clock input that is on AHCLKX (since according to the system configuration manual all devices see the input from a multiplexed pin).  This generates constant modem status interrupts.  I disabled the modem status interrupt in the Linux kernel code and things seem to be behaving more as expected.  Thanks again.

    --James

  • Hi

    I seem to be having the same problem with UART1. I cant seem to trace the modem status interrupt for the experimenter board. There seems to be disparities in the code as to what register to set. Could you please supply the code changes required for the fix?

    Ian

  • Hi,

    I am also having the same problem. I need to use UART1 for my application, UART2 will still be used for console.

    What are the exact code changes to be made to disable CTS (or actually Modem Status Change Interrupts)?

    Since the interrupts are coming from the clcok on the UART1 CTS pin I want to disable that interrupt.

    I have tried this, but with no luck.

    __raw_writel(0, IO_ADDRESS(DA8XX_UART0_BASE) + 0x30); // Disable UART0   
    __raw_writel(0x07, IO_ADDRESS(DA8XX_UART1_BASE) + 0x04 );    // Disable Modem Status Change Interrupt, all other Interrupts are enabled for UART1

  • ../drivers/serial/8250.c

    static void serial8250_enable_ms(struct uart_port *port)
    {
             ...

            //disable modem status interrupt

            //up->ier |= UART_IER_MSI;

           .....

    }

    static void serial8250_set_termios()

    {

      //disable modem status interrupt

          //up->ier |= UART_IER_MSI;

    }

  • The kernel modifications above will work, but will limit *all* of the UARTS to not being able to use flow control, which you might not want.  Also, it is unlikely that these modifications will ever be accepted into the linux kernel mainline, so you'll always need to propagate these changes if you want to move your kernel forward.

    We've fought this problem a couple of different ways, and have determined that if you specify that programs open the ttys in question in line local mode and don't request HW flow control you should not need to modify your kernel as the modem status interrupts should not get enabled.

    In most cases the code that was opening serial ports that created this problem was getty.  All we had to do was specify to getty to use "local line" mode, and the modem status interrupts were not enabled and the problem went away. 

    E.G., in the /etc/inittab file, we changed an entry like this:

    S:2345:respawn:/sbin/getty 115200 ttyS1

    to this:

    S:2345:respawn:/sbin/getty -L 115200 ttyS1

    It's admittedly a work-around (the kernel should protect against this sort of thing), but the core problem is really in the hardware implementation (pin-muxing should really disconnect inputs as well as outputs on the chip, particularly ones that can generate interrupts!).  FWIW.

    -Mike