Example #1
0
static void omap_uart_putc_sleepable(struct omap_uart_port *port, u8 ch)
{
	/* Wait until there is space in the FIFO */
	if (!omap_uart_lowlevel_can_putc(port->base, port->reg_align)) {
		/* Enable the TX interrupt */
		port->ier |= UART_IER_THRI;
		omap_serial_out(port, UART_IER, port->ier);

		/* Wait for completion */
		vmm_completion_wait(&port->write_possible);
	}

	/* Write data to FIFO */
	omap_serial_out(port, UART_THR, ch);
}
Example #2
0
static vmm_irq_return_t omap_uart_irq_handler(int irq_no, void *dev)
{
	u16 iir, lsr;
	struct omap_uart_port *port = (struct omap_uart_port *)dev;

        iir = omap_serial_in(port, UART_IIR);
        if (iir & UART_IIR_NO_INT)
                return VMM_IRQ_NONE;

        lsr = omap_serial_in(port, UART_LSR);

	/* Handle RX FIFO not empty */
         if (iir & (UART_IIR_RLSI | UART_IIR_RTO | UART_IIR_RDI)) {
		if (lsr & UART_LSR_DR) {
			do {
				u8 ch = omap_serial_in(port, UART_RBR);
				serial_rx(port->p, &ch, 1);
			} while (omap_serial_in(port, UART_LSR) &
					      (UART_LSR_DR | UART_LSR_OE));
		} else if (lsr & (UART_LSR_OE | \
				  UART_LSR_PE | \
				  UART_LSR_BI | UART_LSR_FE) ) {
			while (1);
		}
        }

	omap_serial_out(port, UART_IER, port->ier);

	return VMM_IRQ_HANDLED;
}
Example #3
0
static vmm_irq_return_t omap_uart_irq_handler(int irq_no, void *dev)
{
	u16 iir, lsr;
	struct omap_uart_port *port = (struct omap_uart_port *)dev;

        iir = omap_serial_in(port, UART_IIR);
        if (iir & UART_IIR_NO_INT)
                return VMM_IRQ_NONE;

        lsr = omap_serial_in(port, UART_LSR);

	/* Handle RX FIFO not empty */
         if (iir & (UART_IIR_RLSI | UART_IIR_RTO | UART_IIR_RDI)) { 
		if (lsr & UART_LSR_DR) {
			/* Mask RX interrupts till RX FIFO is empty */
			port->ier &= ~(UART_IER_RDI | UART_IER_RLSI);
			/* Signal work completion to sleeping thread */
			vmm_completion_complete(&port->read_possible);
		} else if (lsr & (UART_LSR_OE | UART_LSR_PE | UART_LSR_BI | UART_LSR_FE) ) {
			while(1);
		}
        }

	/* Handle TX FIFO not full */
	if ((lsr & UART_LSR_THRE) && (iir & UART_IIR_THRI)) {
		/* Mask TX interrupts till TX FIFO is full */
		port->ier &= ~UART_IER_THRI;
		/* Signal work completion to sleeping thread */
		vmm_completion_complete(&port->write_possible);
	}

	omap_serial_out(port, UART_IER, port->ier);

	return VMM_IRQ_HANDLED;
}
Example #4
0
static u8 omap_uart_getc_sleepable(struct omap_uart_port *port)
{
	/* Wait until there is data in the FIFO */
	if (!(omap_serial_in(port, UART_LSR) & UART_LSR_DR)) {
		/* Enable the RX interrupt */
		port->ier |= (UART_IER_RDI | UART_IER_RLSI);
		omap_serial_out(port, UART_IER, port->ier);

		/* Wait for completion */
		vmm_completion_wait(&port->read_possible);
	}

	/* Read data to destination */
	return (omap_serial_in(port, UART_RBR));
}
Example #5
0
static int omap_uart_driver_remove(struct vmm_device *dev)
{
	struct omap_uart_port *port = dev->priv;

	if (!port) {
		return VMM_OK;
	}

	/* Mask Rx interrupt */
	port->ier &= ~(UART_IER_RDI | UART_IER_RLSI);
	omap_serial_out(port, UART_IER, port->ier);

	/* Free-up resources */
	serial_destroy(port->p);
	vmm_host_irq_unregister(port->irq, port);
	vmm_devtree_regunmap_release(dev->of_node, port->base, 0);
	vmm_free(port);
	dev->priv = NULL;

	return VMM_OK;
}
Example #6
0
void omap_uart_lowlevel_putc(virtual_addr_t base, u32 reg_align, u8 ch)
{
	while (!omap_uart_lowlevel_can_putc(base, reg_align));

	omap_serial_out(UART_THR, ch);
}
Example #7
0
static int omap_uart_startup_configure(struct omap_uart_port *port)
{
	u16 bdiv, cval;
	bdiv = udiv32(port->input_clock, (16 * port->baudrate));

        /*
         * Clear the FIFO buffers and disable them.
         */
        omap_serial_out(port, UART_FCR, UART_FCR_ENABLE_FIFO);
        omap_serial_out(port, UART_FCR, UART_FCR_ENABLE_FIFO |
                       UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
        omap_serial_out(port, UART_FCR, 0);

        /*
         * Clear the interrupt registers.
         */
        (void) omap_serial_in(port, UART_LSR);
        if (omap_serial_in(port, UART_LSR) & UART_LSR_DR)
                (void) omap_serial_in(port, UART_RBR);
        (void) omap_serial_in(port, UART_IIR);
        (void) omap_serial_in(port, UART_MSR);

        cval = UART_LCR_WLEN8;

        /*
         * Now, initialize the UART
         */
        omap_serial_out(port, UART_LCR, cval);

        /*
         * Finally, enable interrupts
         */
        port->ier = UART_IER_RLSI | UART_IER_RDI;
        omap_serial_out(port, UART_IER, port->ier);

        /* Enable module level wake port */
        omap_serial_out(port, UART_OMAP_WER, OMAP_UART_WER_MOD_WKUP);


        port->fcr = UART_FCR_R_TRIG_01 | UART_FCR_T_TRIG_01 |
                        UART_FCR_ENABLE_FIFO;

        port->ier &= ~UART_IER_MSI;

        omap_serial_out(port, UART_IER, port->ier);
        omap_serial_out(port, UART_LCR, cval);         /* reset DLAB */

        /* FCR can be changed only when the
         * baud clock is not running
         * DLL_REG and DLH_REG set to 0.
         */
        omap_serial_out(port, UART_LCR, UART_LCR_CONF_MODE_A);
        omap_serial_out(port, UART_DLL, 0);
        omap_serial_out(port, UART_DLM, 0);
        omap_serial_out(port, UART_LCR, 0);

        omap_serial_out(port, UART_LCR, UART_LCR_CONF_MODE_B);

        port->efr = omap_serial_in(port, UART_EFR);
        omap_serial_out(port, UART_EFR, port->efr | UART_EFR_ECB);

        omap_serial_out(port, UART_LCR, UART_LCR_CONF_MODE_A);
        port->mcr = omap_serial_in(port, UART_MCR);
        omap_serial_out(port, UART_MCR, port->mcr | UART_MCR_TCRTLR);

        /* FIFO ENABLE, DMA MODE */
        omap_serial_out(port, UART_FCR, port->fcr);
        omap_serial_out(port, UART_LCR, UART_LCR_CONF_MODE_B);

        omap_serial_out(port, UART_EFR, port->efr);
        omap_serial_out(port, UART_LCR, UART_LCR_CONF_MODE_A);
        omap_serial_out(port, UART_MCR, port->mcr);

        /* Protocol, Baud Rate, and Interrupt Settings */

        omap_serial_out(port, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);
        omap_serial_out(port, UART_LCR, UART_LCR_CONF_MODE_B);

        port->efr = omap_serial_in(port, UART_EFR);
        omap_serial_out(port, UART_EFR, port->efr | UART_EFR_ECB);

        omap_serial_out(port, UART_LCR, 0);
        omap_serial_out(port, UART_IER, 0);
        omap_serial_out(port, UART_LCR, UART_LCR_CONF_MODE_B);

        omap_serial_out(port, UART_DLL, bdiv & 0xff);          /* LS of divisor */
        omap_serial_out(port, UART_DLM, bdiv >> 8);            /* MS of divisor */

        omap_serial_out(port, UART_LCR, 0);
        omap_serial_out(port, UART_IER, port->ier);
        omap_serial_out(port, UART_LCR, UART_LCR_CONF_MODE_B);

        omap_serial_out(port, UART_EFR, port->efr);
        omap_serial_out(port, UART_LCR, cval);

        omap_serial_out(port, UART_OMAP_MDR1, UART_OMAP_MDR1_16X_MODE);

        omap_serial_out(port, UART_MCR, port->mcr);

	uart_configure_xonxoff(port);

	return VMM_OK;
}
Example #8
0
void uart_configure_xonxoff(struct omap_uart_port *port)
{
	u16 efr;

	port->lcr = omap_serial_in(port, UART_LCR);
	omap_serial_out(port, UART_LCR, UART_LCR_CONF_MODE_B);
	port->efr = omap_serial_in(port, UART_EFR);
	omap_serial_out(port, UART_EFR, port->efr & ~UART_EFR_ECB);

	omap_serial_out(port, UART_XON1, 0x11);
	omap_serial_out(port, UART_XOFF1, 0x13);

	/* clear SW control mode bits */
	efr = port->efr;
	efr &= OMAP_UART_SW_CLR;

#if 0  /* Enable if required */
	/*
	 * IXON Flag:
	 * Enable XON/XOFF flow control on output.
	 * Transmit XON1, XOFF1
	 */
	efr |= OMAP_UART_SW_TX;

	/*
	 * IXOFF Flag:
	 * Enable XON/XOFF flow control on input.
	 * Receiver compares XON1, XOFF1.
	 */
	efr |= OMAP_UART_SW_RX;
#endif

	omap_serial_out(port, UART_EFR, port->efr | UART_EFR_ECB);
	omap_serial_out(port, UART_LCR, UART_LCR_CONF_MODE_A);

	port->mcr = omap_serial_in(port, UART_MCR);
	omap_serial_out(port, UART_MCR, port->mcr | UART_MCR_TCRTLR);

	omap_serial_out(port, UART_LCR, UART_LCR_CONF_MODE_B);
	omap_serial_out(port, UART_TI752_TCR, OMAP_UART_TCR_TRIG);
	/* Enable special char function UARTi.EFR_REG[5] and
	 * load the new software flow control mode IXON or IXOFF
	 * and restore the UARTi.EFR_REG[4] ENHANCED_EN value.
	 */
	omap_serial_out(port, UART_EFR, efr | UART_EFR_SCD);
	omap_serial_out(port, UART_LCR, UART_LCR_CONF_MODE_A);

	omap_serial_out(port, UART_MCR, port->mcr & ~UART_MCR_TCRTLR);
	omap_serial_out(port, UART_LCR, port->lcr);
}
Example #9
0
void omap_uart_lowlevel_init(virtual_addr_t base, u32 reg_align, 
				u32 baudrate, u32 input_clock)
{
	u16 bdiv;
	bdiv = udiv32(input_clock, (16 * baudrate));

	/* clear interrupt enable reg */
	omap_serial_out(UART_IER, 0);

	/* set mode select to disabled before dll/dlh */
	omap_serial_out(UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);
	omap_serial_out(UART_LCR, UART_LCR_CONF_MODE_A);
	omap_serial_out(UART_DLL, 0);
	omap_serial_out(UART_DLM, 0); 
	omap_serial_out(UART_LCR, 0);

	/* no modem control DTR RTS */
	omap_serial_out(UART_MCR, 0);

	/* enable FIFO */
	omap_serial_out(UART_FCR, UART_FCR_R_TRIG_00 | UART_FCR_T_TRIG_00 | \
			UART_FCR_CLEAR_XMIT | UART_FCR_CLEAR_RCVR | UART_FCR_ENABLE_FIFO);

	/* set baudrate divisor */
	omap_serial_out(UART_LCR, UART_LCR_CONF_MODE_B);
	omap_serial_out(UART_DLL, bdiv & 0xFF);
	omap_serial_out(UART_DLM, (bdiv >> 8) & 0xFF); 
	omap_serial_out(UART_LCR, UART_LCR_WLEN8);

	/* set mode select to 16x mode  */
	omap_serial_out(UART_OMAP_MDR1, UART_OMAP_MDR1_16X_MODE);
}
Example #10
0
static int omap_uart_driver_probe(struct vmm_device *dev,
				  const struct vmm_devtree_nodeid *devid)
{
	int rc;
	struct omap_uart_port *port;
	
	port = vmm_zalloc(sizeof(struct omap_uart_port));
	if (!port) {
		rc = VMM_ENOMEM;
		goto free_nothing;
	}

	rc = vmm_devtree_request_regmap(dev->of_node, &port->base, 0,
					"omap-uart");
	if (rc) {
		goto free_port;
	}

	if (vmm_devtree_read_u32(dev->of_node, "reg-shift",
				 &port->reg_shift)) {
		port->reg_shift = 0;
	}

	if (vmm_devtree_read_u32(dev->of_node, "baudrate",
				 &port->baudrate)) {
		port->baudrate = 115200;
	}

	rc = vmm_devtree_clock_frequency(dev->of_node,
					 &port->input_clock);
	if (rc) {
		goto free_reg;
	}

	omap_uart_startup_configure(port);

	port->irq = vmm_devtree_irq_parse_map(dev->of_node, 0);
	if (!port->irq) {
		rc = VMM_ENODEV;
		goto free_reg;
	}
	if ((rc = vmm_host_irq_register(port->irq, dev->name,
					omap_uart_irq_handler, port))) {
		goto free_reg;
	}

	/* Create Serial Port */
	port->p = serial_create(dev, 256, omap_uart_tx, port);
	if (VMM_IS_ERR_OR_NULL(port->p)) {
		rc = VMM_PTR_ERR(port->p);
		goto free_irq;
	}

	/* Save port pointer */
	dev->priv = port;

	/* Unmask Rx interrupt */
	port->ier |= (UART_IER_RDI | UART_IER_RLSI);
	omap_serial_out(port, UART_IER, port->ier);

	return VMM_OK;

free_irq:
	vmm_host_irq_unregister(port->irq, port);
free_reg:
	vmm_devtree_regunmap_release(dev->of_node, port->base, 0);
free_port:
	vmm_free(port);
free_nothing:
	return rc;
}