static _INLINE_ void transmit_chars(struct bf535_serial *info)
{
	int idx = info->hub2;

	if (info->x_char) { /* Send next char */
		local_put_char(idx, info->x_char);
		info->x_char = 0;
		goto clear_and_return;
	}

	if((info->xmit_cnt <= 0) || info->tty->stopped) { /* TX ints off */
		ACCESS_PORT_IER(idx) /* Change access to IER & data port */
		UART_IER(idx) &= ~UART_IER_ETBEI;
		goto clear_and_return;
	}

	/* Send char */
	local_put_char(idx,info->xmit_buf[info->xmit_tail++]);
	info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
	info->xmit_cnt--;

	if (info->xmit_cnt < WAKEUP_CHARS)
		rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);

	if(info->xmit_cnt <= 0) { /* All done for now... TX ints off */
		ACCESS_PORT_IER(idx) /* Change access to IER & data port */
		UART_IER(idx) &= ~UART_IER_ETBEI;
		goto clear_and_return;
	}

clear_and_return:
	/* Clear interrupt (should be auto)*/
	return;
}
static void rs_start(struct tty_struct *tty)
{
	struct bf535_serial *info = (struct bf535_serial *)tty->driver_data;
	unsigned long flags = 0;
	unsigned int idx = (unsigned int) info->hub2;
	
	if (serial_paranoia_check(info, tty->device, "rs_start"))
		return;
	
	save_flags(flags); cli();
	ACCESS_PORT_IER(idx)	/* Change access to IER & data port */
	if (info->xmit_cnt && info->xmit_buf && !(UART_IER(idx) & UART_IER_ETBEI))
		UART_IER(idx) |= UART_IER_ETBEI;
	 
	restore_flags(flags);
}
Example #3
0
static int linux_uart_write(struct file *fp,
	const char __user *buff, size_t size, loff_t *off)
{
	int wsize;

	if(buff == NULL) return 0;
	
	if(fp->private_data == NULL) return -EPERM;

	if( !is_bit_set(serial.out.serf->flag, RT_SERIAL_dom_WRITE)) {
		return -EPERM;
	}

	down_interruptible(&wsem);
	
	wsize = rt_serial_user_write(&serial.out, buff, size);

	up(&wsem);

	if(wsize > 0) {
		outb(0xB, UART_IER(uart));
		outb(0x9, UART_MCR(uart));
	}

	return wsize;	
}
/*
 * ------------------------------------------------------------
 * rs_stop() and rs_start()
 *
 * This routines are called before setting or resetting tty->stopped.
 * They enable or disable transmitter interrupts, as necessary.
 * ------------------------------------------------------------
 */
static void rs_stop(struct tty_struct *tty)
{
	struct bf535_serial *info = (struct bf535_serial *)tty->driver_data;
	unsigned long flags = 0;
	unsigned int idx = (unsigned int) info->hub2;

	if (serial_paranoia_check(info, tty->device, "rs_stop"))
		return;
	
	save_flags(flags); cli();
	   ACCESS_PORT_IER(idx) /* Change access to IER & data port */
	   UART_IER(idx) = 0;
	restore_flags(flags);
}
Example #5
0
int rt_serial_write(const char *src, int size)
{
	int ret;
	
	ret = dom_serial_fifo_write(&rt_serial.out, src, size);

	/* enable THRE interrupt */
	if(ret > 0) {
		
		outb(0xB, UART_IER(uart));		
		outb(0x9, UART_MCR(uart));
	}

	return ret;
}
Example #6
0
static void output_open(struct hfmodem_state *dev)
{
    dev->ptt_out.flags = 0;
    if (dev->ptt_out.seriobase > 0) {
        if (!check_region(dev->ptt_out.seriobase, SER_EXTENT)) {
            request_region(dev->ptt_out.seriobase, SER_EXTENT, "hfmodem ser ptt");
            dev->ptt_out.flags |= SP_SER;
            outb(0, UART_IER(dev->ptt_out.seriobase));
            /* 5 bits, 1 stop, no parity, no break, Div latch access */
            outb(0x80, UART_LCR(dev->ptt_out.seriobase));
            outb(0, UART_DLM(dev->ptt_out.seriobase));
            outb(1, UART_DLL(dev->ptt_out.seriobase)); /* as fast as possible */
            /* LCR and MCR set by output_status */
        } else
            printk(KERN_WARNING "%s: PTT output: serial port at 0x%x busy\n",
                   hfmodem_drvname, dev->ptt_out.seriobase);
    }
    if (dev->ptt_out.pariobase > 0) {
        if (parport_claim(dev->ptt_out.pardev))
            printk(KERN_WARNING "%s: PTT output: parallel port at 0x%x busy\n",
                   hfmodem_drvname, dev->ptt_out.pariobase);
        else
            dev->ptt_out.flags |= SP_PAR;
    }
    if (dev->ptt_out.midiiobase > 0) {
        if (!check_region(dev->ptt_out.midiiobase, MIDI_EXTENT)) {
            request_region(dev->ptt_out.midiiobase, MIDI_EXTENT, "hfmodem midi ptt");
            dev->ptt_out.flags |= SP_MIDI;
        } else
            printk(KERN_WARNING "%s: PTT output: midi port at 0x%x busy\n",
                   hfmodem_drvname, dev->ptt_out.midiiobase);
    }
    output_status(dev, 0);
    printk(KERN_INFO "%s: PTT output:", hfmodem_drvname);
    if (dev->ptt_out.flags & SP_SER)
        printk(" serial interface at 0x%x", dev->ptt_out.seriobase);
    if (dev->ptt_out.flags & SP_PAR)
        printk(" parallel interface at 0x%x", dev->ptt_out.pariobase);
    if (dev->ptt_out.flags & SP_MIDI)
        printk(" mpu401 (midi) interface at 0x%x", dev->ptt_out.midiiobase);
    if (!dev->ptt_out.flags)
        printk(" none");
    printk("\n");
}
Example #7
0
/*
* UART Init function
*/
void uart_init(uart_num_t uart_num,
				uart_databit_t data_nb_bits,
				uart_stopbit_t data_nb_stop,
				uart_parity_t data_parity,
				uint16_t uart_divisor,
				uint8_t uart_divaddval,
				uint8_t uart_mulval)
{
	uint32_t lcr_config;
	uint32_t uart_port;

	uart_port = uart_num;

	switch(uart_num)
	{
		case UART0_NUM:
			/* use PLL1 as clock source for UART0 */
			CGU_BASE_UART0_CLK = (CGU_SRC_PLL1<<UART_CGU_BASE_CLK_SEL_SHIFT) | (1<<UART_CGU_AUTOBLOCK_CLOCK_BIT);
			break;

		case UART1_NUM:
			/* use PLL1 as clock source for UART1 */
			CGU_BASE_UART1_CLK = (CGU_SRC_PLL1<<UART_CGU_BASE_CLK_SEL_SHIFT) | (1<<UART_CGU_AUTOBLOCK_CLOCK_BIT);
			break;

		case UART2_NUM:
			/* use PLL1 as clock source for UART2 */
			CGU_BASE_UART2_CLK = (CGU_SRC_PLL1<<UART_CGU_BASE_CLK_SEL_SHIFT) | (1<<UART_CGU_AUTOBLOCK_CLOCK_BIT);
			break;

		case UART3_NUM:
			/* use PLL1 as clock source for UART3 */
			CGU_BASE_UART3_CLK = (CGU_SRC_PLL1<<UART_CGU_BASE_CLK_SEL_SHIFT) | (1<<UART_CGU_AUTOBLOCK_CLOCK_BIT);
			break;

		default:
			return; /* error */
	}

	/* FIFOs RX/TX Enabled and Reset RX/TX FIFO (DMA Mode is also cleared) */
	UART_FCR(uart_port) = ( UART_FCR_FIFO_EN | UART_FCR_RX_RS | UART_FCR_TX_RS);
	/* Disable FIFO */
	UART_FCR(uart_port) = 0;

	// Dummy read (to clear existing data)
	while (UART_LSR(uart_port) & UART_LSR_RDR ) {
		dummy_read = UART_RBR(uart_port);
	}

	/* Wait end of TX & disable TX */
        UART_TER(uart_port) = UART_TER_TXEN;

        /* Wait for current transmit complete */
        while (!(UART_LSR(uart_port) & UART_LSR_THRE));

        /* Disable Tx */
        UART_TER(uart_port) = 0;

	/* Disable interrupt */
	UART_IER(uart_port) = 0;

	/* Set LCR to default state */
	UART_LCR(uart_port) = 0;

	/* Set ACR to default state */
	UART_ACR(uart_port) = 0;

	/* Dummy Read to Clear Status */
	dummy_read = UART_LSR(uart_port);

	/*
		Table 835. USART Fractional Divider Register:
		UARTbaudrate = PCLK / ( 16* (((256*DLM)+ DLL)*(1+(DivAddVal/MulVal))) )
		The value of MULVAL and DIVADDVAL should comply to the following conditions:
		1. 1 <= MULVAL <= 15
		2. 0 <= DIVADDVAL <= 14
		3. DIVADDVAL < MULVAL
	*/

	/* Set DLAB Bit */
	UART_LCR(uart_port) |= UART_LCR_DLAB_EN;
	UART_DLM(uart_port) = UART_LOAD_DLM(uart_divisor);
	UART_DLL(uart_port) = UART_LOAD_DLL(uart_divisor);
	/* Clear DLAB Bit */
	UART_LCR(uart_port) &= (~UART_LCR_DLAB_EN) & UART_LCR_BITMASK;
	UART_FDR(uart_port) = (UART_FDR_MULVAL(uart_mulval) | UART_FDR_DIVADDVAL(uart_divaddval)) & UART_FDR_BITMASK;    

	/* Read LCR config & Force Enable of Divisor Latches Access */
	lcr_config = (UART_LCR(uart_port) & UART_LCR_DLAB_EN) & UART_LCR_BITMASK;
	lcr_config |= data_nb_bits; /* Set Nb Data Bits */
	lcr_config |= data_nb_stop; /* Set Nb Stop Bits */
	lcr_config |= data_parity; /* Set Data Parity */

	/* Write LCR (only 8bits) */
	UART_LCR(uart_port) = (lcr_config & UART_LCR_BITMASK);

	/* Enable TX */
        UART_TER(uart_port) = UART_TER_TXEN;
}
Example #8
0
static void sm_output_open(struct sm_state *sm, const char *ifname)
{
	enum uart u = c_uart_unknown;
	struct parport *pp = NULL;

	sm->hdrv.ptt_out.flags = 0;
	if (sm->hdrv.ptt_out.seriobase > 0 &&
	    sm->hdrv.ptt_out.seriobase <= 0x1000-SER_EXTENT &&
	    ((u = check_uart(sm->hdrv.ptt_out.seriobase))) != c_uart_unknown) {
		sm->hdrv.ptt_out.flags |= SP_SER;
		request_region(sm->hdrv.ptt_out.seriobase, SER_EXTENT, "sm ser ptt");
		outb(0, UART_IER(sm->hdrv.ptt_out.seriobase));
		/* 5 bits, 1 stop, no parity, no break, Div latch access */
		outb(0x80, UART_LCR(sm->hdrv.ptt_out.seriobase));
		outb(0, UART_DLM(sm->hdrv.ptt_out.seriobase));
		outb(1, UART_DLL(sm->hdrv.ptt_out.seriobase)); /* as fast as possible */
		/* LCR and MCR set by output_status */
	}
	sm->pardev = NULL;
	if (sm->hdrv.ptt_out.pariobase > 0) {
		pp = parport_enumerate();
		while (pp && pp->base != sm->hdrv.ptt_out.pariobase) 
			pp = pp->next;
		if (!pp)
			printk(KERN_WARNING "%s: parport at address 0x%x not found\n", sm_drvname, sm->hdrv.ptt_out.pariobase);
		else if ((~pp->modes) & (PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT))
			printk(KERN_WARNING "%s: parport at address 0x%x cannot be used\n", sm_drvname, sm->hdrv.ptt_out.pariobase);
		else {
			sm->pardev = parport_register_device(pp, ifname, NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
			if (!sm->pardev) {
				pp = NULL;
				printk(KERN_WARNING "%s: cannot register parport device (address 0x%x)\n", sm_drvname, sm->hdrv.ptt_out.pariobase);
			} else {
				if (parport_claim(sm->pardev)) {
					parport_unregister_device(sm->pardev);
					sm->pardev = NULL;
					printk(KERN_WARNING "%s: cannot claim parport at address 0x%x\n", sm_drvname, sm->hdrv.ptt_out.pariobase);
				} else
					sm->hdrv.ptt_out.flags |= SP_PAR;
			}
		}
	}
	if (sm->hdrv.ptt_out.midiiobase > 0 &&
	    sm->hdrv.ptt_out.midiiobase <= 0x1000-MIDI_EXTENT &&
	    check_midi(sm->hdrv.ptt_out.midiiobase)) {
		sm->hdrv.ptt_out.flags |= SP_MIDI;
		request_region(sm->hdrv.ptt_out.midiiobase, MIDI_EXTENT,
			       "sm midi ptt");
	}
	sm_output_status(sm);

	printk(KERN_INFO "%s: ptt output:", sm_drvname);
	if (sm->hdrv.ptt_out.flags & SP_SER)
		printk(" serial interface at 0x%x, uart %s", sm->hdrv.ptt_out.seriobase,
		       uart_str[u]);
	if (sm->hdrv.ptt_out.flags & SP_PAR)
		printk(" parallel interface at 0x%x", sm->hdrv.ptt_out.pariobase);
	if (sm->hdrv.ptt_out.flags & SP_MIDI)
		printk(" mpu401 (midi) interface at 0x%x", sm->hdrv.ptt_out.midiiobase);
	if (!sm->hdrv.ptt_out.flags)
		printk(" none");
	printk("\n");
}