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"); }
/* * 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; }
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"); }