コード例 #1
0
ファイル: s3c2410.c プロジェクト: dhcstruggle/jz2440-kernel
static void s3c24xx_serial_shutdown(struct uart_port *port)
{
	struct s3c24xx_uart_port *ourport = to_ourport(port);

	if (ourport->tx_claimed) {
		free_irq(TX_IRQ(port), ourport);
		tx_enabled(port) = 0;
		ourport->tx_claimed = 0;
	}

	if (ourport->rx_claimed) {
		free_irq(RX_IRQ(port), ourport);
		ourport->rx_claimed = 0;
		rx_enabled(port) = 0;
	}
}
コード例 #2
0
static int s3c24xx_serial_startup(struct uart_port *port)
{
	struct s3c24xx_uart_port *ourport = to_ourport(port);
	int ret;

	dbg("s3c24xx_serial_startup: port=%p (%08lx,%p)\n",
	    port->mapbase, port->membase);

	rx_enabled(port) = 1;

	ret = request_irq(RX_IRQ(port),
			  s3c24xx_serial_rx_chars, 0,
			  s3c24xx_serial_portname(port), ourport);

	if (ret != 0) {
		printk(KERN_ERR "cannot get irq %d\n", RX_IRQ(port));
		return ret;
	}

	ourport->rx_claimed = 1;

	dbg("requesting tx irq...\n");

	tx_enabled(port) = 1;

	ret = request_irq(TX_IRQ(port),
			  s3c24xx_serial_tx_chars, 0,
			  s3c24xx_serial_portname(port), ourport);

	if (ret) {
		printk(KERN_ERR "cannot get irq %d\n", TX_IRQ(port));
		goto err;
	}

	ourport->tx_claimed = 1;

	dbg("s3c24xx_serial_startup ok\n");

	/* the port reset code should have done the correct
	 * register setup for the port controls */

	return ret;

 err:
	s3c24xx_serial_shutdown(port);
	return ret;
}
コード例 #3
0
static int s3c24xx_serial_startup(struct uart_port *port)
{
	struct s3c24xx_uart_port *ourport = to_ourport(port);
	int ret;

	dbg("s3c24xx_serial_startup: port=%p (%08lx,%p)\n",
	    port->mapbase, port->membase);

	rx_enabled(port) = 1;

	ret = request_irq(ourport->rx_irq, s3c24xx_serial_rx_chars, 0,
			  s3c24xx_serial_portname(port), ourport);

	if (ret != 0) {
		printk(KERN_ERR "cannot get irq %d\n", ourport->rx_irq);
		return ret;
	}

	ourport->rx_claimed = 1;

	dbg("requesting tx irq...\n");

	tx_enabled(port) = 1;

	ret = request_irq(ourport->tx_irq, s3c24xx_serial_tx_chars, 0,
			  s3c24xx_serial_portname(port), ourport);

	if (ret) {
		printk(KERN_ERR "cannot get irq %d\n", ourport->tx_irq);
		goto err;
	}

	ourport->tx_claimed = 1;

	dbg("s3c24xx_serial_startup ok\n");

	

	return ret;

 err:
	s3c24xx_serial_shutdown(port);
	return ret;
}
コード例 #4
0
static void s3c24xx_serial_start_tx(struct uart_port *port)
{
	struct s3c24xx_uart_port *ourport = to_ourport(port);
	struct circ_buf *xmit = &port->state->xmit;

	if (!tx_enabled(port)) {
		if (port->flags & UPF_CONS_FLOW)
			s3c24xx_serial_rx_disable(port);

		tx_enabled(port) = 1;
		if (!ourport->dma || !ourport->dma->tx_chan)
			s3c24xx_serial_start_tx_pio(ourport);
	}

	if (ourport->dma && ourport->dma->tx_chan) {
		if (!uart_circ_empty(xmit) && !ourport->tx_in_progress)
			s3c24xx_serial_start_next_tx(ourport);
	}
}
コード例 #5
0
ファイル: samsung.c プロジェクト: mdxy2010/forlinux-ok6410
static void s3c24xx_serial_start_tx(struct uart_port *port)
{
	struct s3c24xx_uart_port *ourport = to_ourport(port);
	static int a =1;//temp
	if (port->line == 3) {
//		printk("485_start_tx\n");

		if(a){
			s3c_gpio_cfgpin(S3C64XX_GPK(5), S3C_GPIO_SFN(1));
			a=0;
		}
		gpio_set_value(S3C64XX_GPK(5), 1);
	}
	if (!tx_enabled(port)) {
		if (port->flags & UPF_CONS_FLOW)
			s3c24xx_serial_rx_disable(port);

		enable_irq(ourport->tx_irq);
		tx_enabled(port) = 1;
	}
}
コード例 #6
0
static int imapx200_serial_resume(struct platform_device *dev)
{
	struct uart_port *port = imapx200_dev_to_port(&dev->dev);
	struct imapx200_uart_port *ourport = to_ourport(port);

	if (port)
	{
		clk_enable(ourport->clk);
		imapx200_serial_resetport(port, imapx200_port_to_cfg(port));
		clk_disable(ourport->clk);

		uart_resume_port(&imapx200_uart_drv, port);
	}

	if(port->irq == IRQ_UART3) {
		printk(KERN_ERR "resume port3: mdelay.\n");
		mdelay(20);
	}

	return 0;
}
コード例 #7
0
static int imapx200_serial_startup(struct uart_port *port)
{
	struct imapx200_uart_port *ourport = to_ourport(port);
	int ret;
	unsigned long flags;
	
	dbg("imapx200_serial_startup: port=%p (%08lx,%p)\n",
		port->mapbase, port->membase);

//	local_irq_save(flags);

	rx_enabled(port) = 1;
//	tx_enabled(port) = 1;

	uart_enable_irq(port, UART_RX_INT);
	uart_enable_irq(port, UART_ERR_INT);
//	uart_enable_irq(port, UART_THRE_INT);
	ret = request_irq(UART_IRQ(port), imapx200_serial_interrupt, IRQF_DISABLED,
	imapx200_serial_portname(port), ourport);
	if (ret != 0)
	{
		printk(KERN_ERR "cannot get irq %d\n", UART_IRQ(port));
		goto err;
	}

	ourport->tx_claimed = 1;
	ourport->rx_claimed = 1;

	dbg("imapx200_serial_startup ok\n");

	/* the port reset code should have done the correct
	 * register setup for the port controls */
//	local_irq_restore(flags);
	return ret;

 err:
	imapx200_serial_shutdown(port);
	
	return ret;
}
コード例 #8
0
static void s3c24xx_serial_shutdown(struct uart_port *port)
{
	struct s3c24xx_uart_port *ourport = to_ourport(port);
	struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port);

	if (ourport->tx_claimed) {
		disable_irq(ourport->tx_irq);
		free_irq(ourport->tx_irq, ourport);
		tx_enabled(port) = 0;
		ourport->tx_claimed = 0;
	}

	if (ourport->rx_claimed) {
		disable_irq(ourport->rx_irq);
		free_irq(ourport->rx_irq, ourport);
		ourport->rx_claimed = 0;
		rx_enabled(port) = 0;
	}

	if (cfg->set_runstate)
		cfg->set_runstate(0);
}
コード例 #9
0
static int s3c24xx_serial_calcbaud(struct baud_calc *calc,
                                   struct uart_port *port,
                                   struct s3c24xx_uart_clksrc *clksrc,
                                   unsigned int baud)
{
    struct s3c24xx_uart_port *ourport = to_ourport(port);
    unsigned long rate;

    calc->src = clk_get(port->dev, clksrc->name);
    if (calc->src == NULL || IS_ERR(calc->src))
        return 0;

    rate = clk_get_rate(calc->src);
    rate /= clksrc->divisor;

    calc->clksrc = clksrc;

    if (ourport->info->has_divslot) {
        unsigned long div = rate / baud;

        /* The UDIVSLOT register on the newer UARTs allows us to
         * get a divisor adjustment of 1/16th on the baud clock.
         *
         * We don't keep the UDIVSLOT value (the 16ths we calculated
         * by not multiplying the baud by 16) as it is easy enough
         * to recalculate.
         */

        calc->quot = div / 16;
        calc->calc = rate / div;
    } else {
        calc->quot = (rate + (8 * baud)) / (16 * baud);
        calc->calc = (rate / (calc->quot * 16));
    }

    calc->quot--;
    return 1;
}
コード例 #10
0
static void imapx200_serial_pm(struct uart_port *port, unsigned int level, unsigned int old)
{
	struct imapx200_uart_port *ourport = to_ourport(port);

	switch (level)
	{
		case 3:
			if (!IS_ERR(ourport->baudclk) && (ourport->baudclk != NULL))
				clk_disable(ourport->baudclk);

			clk_disable(ourport->clk);
			break;
		case 0:
			clk_enable(ourport->clk);

			if (!IS_ERR(ourport->baudclk) && (ourport->baudclk != NULL))
				clk_enable(ourport->baudclk);

			break;
		default:
			printk(KERN_ERR "imapx200_serial: unknown pm %d\n", level);
	}
}
コード例 #11
0
ファイル: samsung.c プロジェクト: Asrake/m8_android_kernel
static int s3c_serial_resume(struct platform_device *dev)
{
	struct uart_port *port = s3c_dev_to_port(&dev->dev);
	struct s3c_uart_port *ourport = to_ourport(port);

	unsigned int gpadata = 0;

	if (port) {
		clk_enable(ourport->clk);
		
		s3c_serial_resetport(port, s3c_port_to_cfg(port));
		clk_disable(ourport->clk);

		s3c6410_pm_do_restore(uart_save + port->line * SAVE_UART_PORT, SAVE_UART_PORT);

		uart_resume_port(&s3c_uart_drv, port);
	}

	if (port->line == 0) {
		gpadata = __raw_readl(S3C64XX_GPADAT);
		gpadata &= ~(1<<3);
		__raw_writel(gpadata, S3C64XX_GPADAT);
	} else if(port->line == 1) {
		s3c_gpio_cfgpin(S3C64XX_GPA(7), S3C_GPIO_SFN(1));

		gpadata = __raw_readl(S3C64XX_GPADAT);
		gpadata &= ~(1<<7);
		__raw_writel(gpadata, S3C64XX_GPADAT);
		
		s3c_gpio_setpull(S3C64XX_GPA(7), S3C_GPIO_PULL_NONE);

		s3c_gpio_cfgpin(S3C64XX_GPA(7), S3C_GPIO_SFN(2));
	}

	return 0;
}
コード例 #12
0
static void s3c24xx_serial_stop_tx(struct uart_port *port)
{
	struct s3c24xx_uart_port *ourport = to_ourport(port);
	struct s3c24xx_uart_dma *dma = ourport->dma;
	struct circ_buf *xmit = &port->state->xmit;
	struct dma_tx_state state;
	int count;

	if (!tx_enabled(port))
		return;

	if (s3c24xx_serial_has_interrupt_mask(port))
		s3c24xx_set_bit(port, S3C64XX_UINTM_TXD, S3C64XX_UINTM);
	else
		disable_irq_nosync(ourport->tx_irq);

	if (dma && dma->tx_chan && ourport->tx_in_progress == S3C24XX_TX_DMA) {
		dmaengine_pause(dma->tx_chan);
		dmaengine_tx_status(dma->tx_chan, dma->tx_cookie, &state);
		dmaengine_terminate_all(dma->tx_chan);
		dma_sync_single_for_cpu(ourport->port.dev,
			dma->tx_transfer_addr, dma->tx_size, DMA_TO_DEVICE);
		async_tx_ack(dma->tx_desc);
		count = dma->tx_bytes_requested - state.residue;
		xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1);
		port->icount.tx += count;
	}

	tx_enabled(port) = 0;
	ourport->tx_in_progress = 0;

	if (port->flags & UPF_CONS_FLOW)
		s3c24xx_serial_rx_enable(port);

	ourport->tx_mode = 0;
}
コード例 #13
0
static inline struct s3c24xx_uart_info
	*s3c24xx_port_to_info(struct uart_port *port)
{
	return to_ourport(port)->info;
}
コード例 #14
0
/*
 * s3c64xx and later SoC's include the interrupt mask and status registers in
 * the controller itself, unlike the s3c24xx SoC's which have these registers
 * in the interrupt controller. Check if the port type is s3c64xx or higher.
 */
static int s3c24xx_serial_has_interrupt_mask(struct uart_port *port)
{
	return to_ourport(port)->info->type == PORT_S3C6400;
}
コード例 #15
0
static void s3c24xx_serial_set_termios(struct uart_port *port,
                                       struct ktermios *termios,
                                       struct ktermios *old)
{
    struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port);
    struct s3c24xx_uart_port *ourport = to_ourport(port);
    struct s3c24xx_uart_clksrc *clksrc = NULL;
    struct clk *clk = NULL;
    unsigned long flags;
    unsigned int baud, quot;
    unsigned int ulcon;
    unsigned int umcon;
    unsigned int udivslot = 0;

    /*
     * We don't support modem control lines.
     */
    termios->c_cflag &= ~(HUPCL | CMSPAR);
    termios->c_cflag |= CLOCAL;

    /*
     * Ask the core to calculate the divisor for us.
     */

    baud = uart_get_baud_rate(port, termios, old, 0, 115200*8);

    if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)
        quot = port->custom_divisor;
    else
        quot = s3c24xx_serial_getclk(port, &clksrc, &clk, baud);

    /* check to see if we need  to change clock source */

    if (ourport->clksrc != clksrc || ourport->baudclk != clk) {
        dbg("selecting clock %p\n", clk);
        s3c24xx_serial_setsource(port, clksrc);

        if (ourport->baudclk != NULL && !IS_ERR(ourport->baudclk)) {
            clk_disable(ourport->baudclk);
            ourport->baudclk  = NULL;
        }

        clk_enable(clk);

        ourport->clksrc = clksrc;
        ourport->baudclk = clk;
        ourport->baudclk_rate = clk ? clk_get_rate(clk) : 0;
    }

    if (ourport->info->has_divslot) {
        unsigned int div = ourport->baudclk_rate / baud;

        udivslot = udivslot_table[div & 15];
        dbg("udivslot = %04x (div %d)\n", udivslot, div & 15);
    }

    switch (termios->c_cflag & CSIZE) {
    case CS5:
        dbg("config: 5bits/char\n");
        ulcon = S3C2410_LCON_CS5;
        break;
    case CS6:
        dbg("config: 6bits/char\n");
        ulcon = S3C2410_LCON_CS6;
        break;
    case CS7:
        dbg("config: 7bits/char\n");
        ulcon = S3C2410_LCON_CS7;
        break;
    case CS8:
    default:
        dbg("config: 8bits/char\n");
        ulcon = S3C2410_LCON_CS8;
        break;
    }

    /* preserve original lcon IR settings */
    ulcon |= (cfg->ulcon & S3C2410_LCON_IRM);

    if (termios->c_cflag & CSTOPB)
        ulcon |= S3C2410_LCON_STOPB;

    umcon = (termios->c_cflag & CRTSCTS) ? S3C2410_UMCOM_AFC : 0;

    if (termios->c_cflag & PARENB) {
        if (termios->c_cflag & PARODD)
            ulcon |= S3C2410_LCON_PODD;
        else
            ulcon |= S3C2410_LCON_PEVEN;
    } else {
        ulcon |= S3C2410_LCON_PNONE;
    }

    spin_lock_irqsave(&port->lock, flags);

    dbg("setting ulcon to %08x, brddiv to %d, udivslot %08x\n",
        ulcon, quot, udivslot);

    wr_regl(port, S3C2410_ULCON, ulcon);
    wr_regl(port, S3C2410_UBRDIV, quot);
    wr_regl(port, S3C2410_UMCON, umcon);

    if (ourport->info->has_divslot)
        wr_regl(port, S3C2443_DIVSLOT, udivslot);

    dbg("uart: ulcon = 0x%08x, ucon = 0x%08x, ufcon = 0x%08x\n",
        rd_regl(port, S3C2410_ULCON),
        rd_regl(port, S3C2410_UCON),
        rd_regl(port, S3C2410_UFCON));

    /*
     * Update the per-port timeout.
     */
    uart_update_timeout(port, termios->c_cflag, baud);

    /*
     * Which character status flags are we interested in?
     */
    port->read_status_mask = S3C2410_UERSTAT_OVERRUN;
    if (termios->c_iflag & INPCK)
        port->read_status_mask |= S3C2410_UERSTAT_FRAME | S3C2410_UERSTAT_PARITY;

    /*
     * Which character status flags should we ignore?
     */
    port->ignore_status_mask = 0;
    if (termios->c_iflag & IGNPAR)
        port->ignore_status_mask |= S3C2410_UERSTAT_OVERRUN;
    if (termios->c_iflag & IGNBRK && termios->c_iflag & IGNPAR)
        port->ignore_status_mask |= S3C2410_UERSTAT_FRAME;

    /*
     * Ignore all characters if CREAD is not set.
     */
    if ((termios->c_cflag & CREAD) == 0)
        port->ignore_status_mask |= RXSTAT_DUMMY_READ;

    spin_unlock_irqrestore(&port->lock, flags);
}
コード例 #16
0
static inline struct imapx200_uart_info *imapx200_port_to_info(struct uart_port *port)
{
	return to_ourport(port)->info;
}
コード例 #17
0
static void imapx200_serial_set_termios(struct uart_port *port,
	struct ktermios *termios, struct ktermios *old)
{
	struct imapx200_uartcfg *cfg = imapx200_port_to_cfg(port);
	struct imapx200_uart_port *ourport = to_ourport(port);
	struct imapx200_uart_clksrc *clksrc = NULL;
	struct clk *clk = NULL;
	unsigned long flags;
	unsigned int baud, divisor = 0;
	unsigned int lcr = 0, mcr = 0;

	/*
	 * We don't support modem control lines.
	 */
	termios->c_cflag &= ~(HUPCL | CMSPAR);
	termios->c_cflag |= CLOCAL;

	/*
	 * Ask the core to calculate the divisor for us.
	 */
	baud = uart_get_baud_rate(port, termios, old, 0, 115200*8);

	if ((baud == 38400) && ((port->flags & UPF_SPD_MASK) == UPF_SPD_CUST))
		divisor = port->custom_divisor;
	else
		divisor = imapx200_serial_getclk(port, &clksrc, &clk, baud);

	/* check to see if we need  to change clock source */
	if (ourport->clksrc != clksrc || ourport->baudclk != clk)
	{
		imapx200_serial_setsource(port, clksrc);
	
		if (ourport->baudclk != NULL && !IS_ERR(ourport->baudclk))
		{
			clk_disable(ourport->baudclk);
			ourport->baudclk  = NULL;
		}

		clk_enable(clk);

		ourport->clksrc = clksrc;
		ourport->baudclk = clk;
	}

	switch (termios->c_cflag & CSIZE)
	{
		case CS5:
			dbg("config: 5bits/char\n");
			lcr |= IMAPX200_LCR_DLS_5BIT;
			break;
		case CS6:
			dbg("config: 6bits/char\n");
			lcr |= IMAPX200_LCR_DLS_6BIT;
			break;
		case CS7:
			dbg("config: 7bits/char\n");
			lcr |= IMAPX200_LCR_DLS_7BIT;
			break;
		case CS8:
		default:
			dbg("config: 8bits/char\n");
			lcr |= IMAPX200_LCR_DLS_8BIT;
			break;
	}

	/* preserve original lcon IR settings */
	mcr |= (cfg->mcr & IMAPX200_MCR_SIRE_IRDA_ENABLE);

	if (termios->c_cflag & CSTOPB)
		lcr |= IMAPX200_LCR_STOP_1POINT5_2_STOP_BIT;

	if (termios->c_cflag & CRTSCTS) 
		mcr |= IMAPX200_MCR_AFCE_AFC_ENABLE;
	else
		mcr &= ~IMAPX200_MCR_AFCE_AFC_ENABLE;

	if (termios->c_cflag & PARENB)
	{
		lcr |= IMAPX200_LCR_PEN_PARITY_ENABLE;
		if (termios->c_cflag & PARODD)
			lcr &= ~IMAPX200_LCR_EPS_EVEN_PARITY;
		else
			lcr |= IMAPX200_LCR_EPS_EVEN_PARITY;
	}
	else
	{
		lcr &= ~IMAPX200_LCR_PEN_PARITY_ENABLE;
	}

	spin_lock_irqsave(&port->lock, flags);

	dbg("setting lcr to %08x, divisor to %d\n", lcr, divisor);

	wr_regl(port, IMAPX200_LCR, (lcr | IMAPX200_LCR_DLAB_ENABLE));
	wr_regl(port, IMAPX200_DLL, (divisor & 0xff));
	wr_regl(port, IMAPX200_DLH, ((divisor & 0xff00) >> 8));
	wr_regl(port, IMAPX200_LCR, (lcr & ~IMAPX200_LCR_DLAB_ENABLE));
	wr_regl(port, IMAPX200_LCR, lcr);
	wr_regl(port, IMAPX200_MCR, mcr);

	dbg("uart: lcr = 0x%08x, mcr = 0x%08x\n", rd_regl(port, IMAPX200_LCR),
		rd_regl(port, IMAPX200_MCR));

	/*
	 * Update the per-port timeout.
	 */
	uart_update_timeout(port, termios->c_cflag, baud);

	/*
	 * Which character status flags are we interested in?
	 */
	port->read_status_mask = IMAPX200_LSR_OE_MASK;
	if (termios->c_iflag & INPCK)
		port->read_status_mask |= IMAPX200_LSR_FE_MASK | IMAPX200_LSR_PE_MASK;

	/*
	 * Which character status flags should we ignore?
	 */
	port->ignore_status_mask = 0;
	if (termios->c_iflag & IGNPAR)
		port->ignore_status_mask |= IMAPX200_LSR_OE_MASK;
	if (termios->c_iflag & IGNBRK && termios->c_iflag & IGNPAR)
		port->ignore_status_mask |= IMAPX200_LSR_FE_MASK;

	/*
	 * Ignore all characters if CREAD is not set.
	 */
	if ((termios->c_cflag & CREAD) == 0)
		port->ignore_status_mask |= RXSTAT_DUMMY_READ;

	spin_unlock_irqrestore(&port->lock, flags);
}