static void msm_hsl_enable_ms(struct uart_port *port) { struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port); clk_en(port, 1); msm_hsl_port->imr |= UARTDM_ISR_DELTA_CTS_BMSK; msm_hsl_write(port, msm_hsl_port->imr, UARTDM_IMR_ADDR); clk_en(port, 0); }
/* * Wait for transmitter & holding register to empty * Derived from wait_for_xmitr in 8250 serial driver by Russell King */ void wait_for_xmitr(struct uart_port *port, int bits) { if (!(msm_hsl_read(port, UARTDM_SR_ADDR) & UARTDM_SR_TXEMT_BMSK)) { while ((msm_hsl_read(port, UARTDM_ISR_ADDR) & bits) != bits) { udelay(1); touch_nmi_watchdog(); cpu_relax(); } msm_hsl_write(port, CLEAR_TX_READY, UARTDM_CR_ADDR); } }
static void msm_hsl_start_tx(struct uart_port *port) { struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port); clk_en(port, 1); msm_hsl_port->imr |= UARTDM_ISR_TXLEV_BMSK; msm_hsl_write(port, msm_hsl_port->imr, UARTDM_IMR_ADDR); clk_en(port, 0); }
static void msm_hsl_stop_rx(struct uart_port *port) { struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port); clk_en(port, 1); msm_hsl_port->imr &= ~(UARTDM_ISR_RXLEV_BMSK | UARTDM_ISR_RXSTALE_BMSK); msm_hsl_write(port, msm_hsl_port->imr, UARTDM_IMR_ADDR); clk_en(port, 0); }
static void msm_hsl_enable_ms_cir(struct uart_port *port) { struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port); clk_en(port, 1); pr_info("%s () :port->line %d, ir\n", __func__, port->line); msm_hsl_port->imr |= UARTDM_ISR_DELTA_CTS_BMSK; msm_hsl_write(port, msm_hsl_port->imr, regmap[msm_hsl_port->ver_id][UARTDM_IMR]); clk_en(port, 0); }
static void msm_hsl_start_tx_cir(struct uart_port *port) { struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port); clk_en(port, 1); msm_hsl_port->imr |= UARTDM_ISR_TXLEV_BMSK; msm_hsl_write(port, msm_hsl_port->imr, regmap[msm_hsl_port->ver_id][UARTDM_IMR]); clk_en(port, 0); }
static irqreturn_t msm_hsl_irq(int irq, void *dev_id) { struct uart_port *port = dev_id; struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port); unsigned int vid; unsigned int misr; unsigned long flags; spin_lock_irqsave(&port->lock, flags); clk_en(port, 1); vid = msm_hsl_port->ver_id; misr = msm_hsl_read(port, regmap[vid][UARTDM_MISR]); msm_hsl_write(port, 0, regmap[vid][UARTDM_IMR]); if (misr & (UARTDM_ISR_RXSTALE_BMSK | UARTDM_ISR_RXLEV_BMSK)) { handle_rx(port, misr); if (misr & (UARTDM_ISR_RXSTALE_BMSK)) { msm_hsl_write(port, RESET_STALE_INT, regmap[vid][UARTDM_CR]); } msm_hsl_write(port, 6500, regmap[vid][UARTDM_DMRX]); msm_hsl_write(port, STALE_EVENT_ENABLE, regmap[vid][UARTDM_CR]); } if (misr & UARTDM_ISR_TXLEV_BMSK) handle_tx(port); if (misr & UARTDM_ISR_DELTA_CTS_BMSK) handle_delta_cts(port); msm_hsl_write(port, msm_hsl_port->imr, regmap[vid][UARTDM_IMR]); clk_en(port, 0); spin_unlock_irqrestore(&port->lock, flags); return IRQ_HANDLED; }
static void msm_hsl_stop_rx_cir(struct uart_port *port) { struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port); clk_en(port, 1); pr_info("%s () :port->line %d, ir\n", __func__, port->line); msm_hsl_port->imr &= ~(UARTDM_ISR_RXLEV_BMSK | UARTDM_ISR_RXSTALE_BMSK); msm_hsl_write(port, msm_hsl_port->imr, regmap[msm_hsl_port->ver_id][UARTDM_IMR]); clk_en(port, 0); }
static void msm_hsl_set_mctrl_cir(struct uart_port *port, unsigned int mctrl) { unsigned int vid = UART_TO_MSM(port)->ver_id; unsigned int mr; unsigned int loop_mode; clk_en(port, 1); mr = msm_hsl_read(port, regmap[vid][UARTDM_MR1]); if (!(mctrl & TIOCM_RTS)) { pr_info("%s ()mctrl & TIOCM_RTS:port->line %d, ir\n", __func__, port->line); mr &= ~UARTDM_MR1_RX_RDY_CTL_BMSK; msm_hsl_write(port, mr, regmap[vid][UARTDM_MR1]); msm_hsl_write(port, RFR_HIGH, regmap[vid][UARTDM_CR]); } else { mr |= UARTDM_MR1_RX_RDY_CTL_BMSK; msm_hsl_write(port, mr, regmap[vid][UARTDM_MR1]); pr_info("%s () TIOCM_RTS:port->line %d, ir\n", __func__, port->line); } loop_mode = TIOCM_LOOP & mctrl; if (loop_mode) { pr_info("%s ()loop_mode:port->line %d, ir\n", __func__, port->line); mr = msm_hsl_read(port, regmap[vid][UARTDM_MR2]); mr |= UARTDM_MR2_LOOP_MODE_BMSK; msm_hsl_write(port, mr, regmap[vid][UARTDM_MR2]); msm_hsl_reset(port); msm_hsl_write(port, UARTDM_CR_RX_EN_BMSK | UARTDM_CR_TX_EN_BMSK, regmap[vid][UARTDM_CR]); } clk_en(port, 0); }
static void msm_hsl_console_putchar(struct uart_port *port, int ch) { unsigned int vid = UART_TO_MSM(port)->ver_id; wait_for_xmitr(port, UARTDM_ISR_TX_READY_BMSK); msm_hsl_write(port, 1, regmap[vid][UARTDM_NCF_TX]); #if 1 while (!(msm_hsl_read(port, regmap[vid][UARTDM_SR]) & UARTDM_SR_TXRDY_BMSK)) { udelay(1); touch_nmi_watchdog(); } #else /* * Dummy read to add 1 AHB clock delay to fix UART hardware bug. * Bug: Delay required on TX-transfer-init. after writing to * NO_CHARS_FOR_TX register. */ msm_hsl_read(port, regmap[vid][UARTDM_SR]); #endif msm_hsl_write(port, ch, regmap[vid][UARTDM_TF]); D("%s ():port->line %d, ir\n", __func__, port->line); }
static void msm_hsl_reset(struct uart_port *port) { /* reset everything */ msm_hsl_write(port, RESET_RX, UARTDM_CR_ADDR); msm_hsl_write(port, RESET_TX, UARTDM_CR_ADDR); msm_hsl_write(port, RESET_ERROR_STATUS, UARTDM_CR_ADDR); msm_hsl_write(port, RESET_BREAK_INT, UARTDM_CR_ADDR); msm_hsl_write(port, RESET_CTS, UARTDM_CR_ADDR); msm_hsl_write(port, RFR_LOW, UARTDM_CR_ADDR); }
/* * Wait for transmitter & holding register to empty * Derived from wait_for_xmitr in 8250 serial driver by Russell King */ void wait_for_xmitr(struct uart_port *port, int bits) { unsigned int vid = UART_TO_MSM(port)->ver_id; if (!(msm_hsl_read(port, regmap[vid][UARTDM_SR]) & UARTDM_SR_TXEMT_BMSK)) { while ((msm_hsl_read(port, regmap[vid][UARTDM_ISR]) & bits) != bits) { udelay(1); touch_nmi_watchdog(); cpu_relax(); } msm_hsl_write(port, CLEAR_TX_READY, regmap[vid][UARTDM_CR]); } D("%s ():port->line %d, ir\n", __func__, port->line); }
static void msm_hsl_start_tx(struct uart_port *port) { struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port); struct circ_buf *xmit = &port->state->xmit; if(b_terminal_onoff == 0 && console_uart_port && (port == console_uart_port)){ uart_circ_clear(xmit); return; } clk_en(port, 1); msm_hsl_port->imr |= UARTDM_ISR_TXLEV_BMSK; msm_hsl_write(port, msm_hsl_port->imr, UARTDM_IMR_ADDR); clk_en(port, 0); }
static void msm_hsl_reset(struct uart_port *port) { unsigned int vid = UART_TO_MSM(port)->ver_id; /* reset everything */ msm_hsl_write(port, RESET_RX, regmap[vid][UARTDM_CR]); msm_hsl_write(port, RESET_TX, regmap[vid][UARTDM_CR]); msm_hsl_write(port, RESET_ERROR_STATUS, regmap[vid][UARTDM_CR]); msm_hsl_write(port, RESET_BREAK_INT, regmap[vid][UARTDM_CR]); msm_hsl_write(port, RESET_CTS, regmap[vid][UARTDM_CR]); msm_hsl_write(port, RFR_LOW, regmap[vid][UARTDM_CR]); }
static void msm_hsl_reset(struct uart_port *port) { unsigned int vid = UART_TO_MSM(port)->ver_id; pr_info("%s ():port->line %d, ir\n", __func__, port->line); msm_hsl_write(port, RESET_RX, regmap[vid][UARTDM_CR]); msm_hsl_write(port, RESET_TX, regmap[vid][UARTDM_CR]); msm_hsl_write(port, RESET_ERROR_STATUS, regmap[vid][UARTDM_CR]); msm_hsl_write(port, RESET_BREAK_INT, regmap[vid][UARTDM_CR]); msm_hsl_write(port, RESET_CTS, regmap[vid][UARTDM_CR]); msm_hsl_write(port, RFR_LOW, regmap[vid][UARTDM_CR]); }
static void msm_hsl_shutdown_irda(struct uart_port *port) { struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port); msm_hsl_port->imr = 0; /* disable interrupts */ msm_hsl_write(port, 0, regmap[msm_hsl_port->ver_id][UARTDM_IMR]); free_irq(port->irq, port); #ifndef CONFIG_PM_RUNTIME msm_hsl_deinit_clock(port); #endif pm_runtime_put_sync(port->dev); if (!(is_console(port)) || (!port->cons) || (port->cons && (!(port->cons->flags & CON_ENABLED)))) { } }
static void msm_hsl_shutdown(struct uart_port *port) { struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port); clk_en(port, 1); msm_hsl_port->imr = 0; msm_hsl_write(port, 0, UARTDM_IMR_ADDR); /* disable interrupts */ clk_en(port, 0); free_irq(port->irq, port); #ifndef CONFIG_PM_RUNTIME msm_hsl_deinit_clock(port); #endif pm_runtime_put_sync(port->dev); }
static ssize_t enable_cir_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct msm_hsl_port *msm_cir_port = htc_cir_port; struct uart_port *port = &(msm_cir_port->uart); unsigned long flags; int cir_en, ret = 0; sscanf(buf, "%d", &cir_en); if (cir_en != 1 && cir_en != 3 && cir_en != 0) D("%s: parameter invalid. cir_en = %d", __func__, cir_en); D("%s: (cir_enable_flg, cir_en) = (%d, %d)\n", __func__, cir_enable_flg, cir_en); ret = clk_set_rate(msm_cir_port->clk, 7372800); if (!ret) { clk_en(port, 1); D("%s(): irda Clock enabled for line(%d)\n", __func__, port->line); } else { D("%s(): Error: Setting the clock rate\n", __func__); return -EINVAL; } if (cir_en > 1) { D("%s(): Set IRDA mode\n", __func__); spin_lock_irqsave(&port->lock, flags); ret = 1; ret |= (int)cir_en; msm_hsl_write(port, ret, UARTDM_IRDA_ADDR); spin_unlock_irqrestore(&port->lock, flags); cir_enable_flg = PATH_IRDA; if (msm_cir_port->cir_set_path) msm_cir_port->cir_set_path(PATH_IRDA); } clk_en(port, 0); return count; }
static void msm_hsl_shutdown_cir(struct uart_port *port) { struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port); clk_en(port, 1); pr_info("%s () :port->line %d, ir\n", __func__, port->line); msm_hsl_port->imr = 0; msm_hsl_write(port, 0, regmap[msm_hsl_port->ver_id][UARTDM_IMR]); clk_en(port, 0); free_irq(port->irq, port); #ifndef CONFIG_PM_RUNTIME msm_hsl_deinit_clock(port); #endif pm_runtime_put_sync(port->dev); if (!(is_console(port)) || (!port->cons) || (port->cons && (!(port->cons->flags & CON_ENABLED)))) { pr_info("%s () is_console:port->line %d, ir\n", __func__, port->line); } }
static void msm_hsl_power_cir(struct uart_port *port, unsigned int state, unsigned int oldstate) { int ret; struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port); unsigned long flags; D("%s (): ir, state %d\n", __func__, state); switch (state) { case 0: ret = clk_set_rate(msm_hsl_port->clk, 7372800); if (ret) E("%s(): Error setting UART clock rate\n", __func__); clk_en(port, 1); break; case 3: if (cir_enable_flg != PATH_CIR) { D("%s path is not CIR. flg = %d\n", __func__, cir_enable_flg); D("%s(): Clear IRDA mode \n", __func__); spin_lock_irqsave(&port->lock, flags); ret = 0; msm_hsl_write(port, ret, UARTDM_IRDA_ADDR); spin_unlock_irqrestore(&port->lock, flags); cir_enable_flg = PATH_CIR; if (msm_hsl_port->cir_set_path) msm_hsl_port->cir_set_path(PATH_CIR); } clk_en(port, 0); break; default: E("%s(): msm_serial_hsl: Unknown PM state %d\n", __func__, state); } }
static void msm_hsl_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { unsigned long flags; unsigned int baud, mr; spin_lock_irqsave(&port->lock, flags); clk_en(port, 1); /* calculate and set baud rate */ /* [FELICA_S] [email protected] 20110419 */ /* change default baudrate for felica */ #ifdef CONFIG_LGE_FELICA if (port->line == 3) { termios->c_cflag |= B460800; baud = uart_get_baud_rate(port, termios, old, 300, 460800); msm_hsl_set_baud_rate(port, baud); } else { baud = uart_get_baud_rate(port, termios, old, 300, 115200); msm_hsl_set_baud_rate(port, baud); } #else baud = uart_get_baud_rate(port, termios, old, 300, 460800); msm_hsl_set_baud_rate(port, baud); #endif /* [FELICA_E] [email protected] 20110419 */ /* calculate parity */ mr = msm_hsl_read(port, UARTDM_MR2_ADDR); mr &= ~UARTDM_MR2_PARITY_MODE_BMSK; if (termios->c_cflag & PARENB) { if (termios->c_cflag & PARODD) mr |= ODD_PARITY; else if (termios->c_cflag & CMSPAR) mr |= SPACE_PARITY; else mr |= EVEN_PARITY; } /* calculate bits per char */ mr &= ~UARTDM_MR2_BITS_PER_CHAR_BMSK; switch (termios->c_cflag & CSIZE) { case CS5: mr |= FIVE_BPC; break; case CS6: mr |= SIX_BPC; break; case CS7: mr |= SEVEN_BPC; break; case CS8: default: mr |= EIGHT_BPC; break; } /* calculate stop bits */ mr &= ~(STOP_BIT_ONE | STOP_BIT_TWO); if (termios->c_cflag & CSTOPB) mr |= STOP_BIT_TWO; else mr |= STOP_BIT_ONE; /* set parity, bits per char, and stop bit */ msm_hsl_write(port, mr, UARTDM_MR2_ADDR); /* calculate and set hardware flow control */ mr = msm_hsl_read(port, UARTDM_MR1_ADDR); mr &= ~(UARTDM_MR1_CTS_CTL_BMSK | UARTDM_MR1_RX_RDY_CTL_BMSK); if (termios->c_cflag & CRTSCTS) { mr |= UARTDM_MR1_CTS_CTL_BMSK; mr |= UARTDM_MR1_RX_RDY_CTL_BMSK; } msm_hsl_write(port, mr, UARTDM_MR1_ADDR); /* Configure status bits to ignore based on termio flags. */ port->read_status_mask = 0; if (termios->c_iflag & INPCK) port->read_status_mask |= UARTDM_SR_PAR_FRAME_BMSK; if (termios->c_iflag & (BRKINT | PARMRK)) port->read_status_mask |= UARTDM_SR_RX_BREAK_BMSK; uart_update_timeout(port, termios->c_cflag, baud); clk_en(port, 0); spin_unlock_irqrestore(&port->lock, flags); }
static int msm_hsl_startup(struct uart_port *port) { struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port); struct platform_device *pdev = to_platform_device(port->dev); const struct msm_serial_hslite_platform_data *pdata = pdev->dev.platform_data; unsigned int data, rfr_level; int ret; unsigned long flags; snprintf(msm_hsl_port->name, sizeof(msm_hsl_port->name), "msm_serial_hsl%d", port->line); if (!(is_console(port)) || (!port->cons) || (port->cons && (!(port->cons->flags & CON_ENABLED)))) { if (msm_serial_hsl_has_gsbi()) if ((ioread32(msm_hsl_port->mapped_gsbi + GSBI_CONTROL_ADDR) & GSBI_PROTOCOL_I2C_UART) != GSBI_PROTOCOL_I2C_UART) iowrite32(GSBI_PROTOCOL_I2C_UART, msm_hsl_port->mapped_gsbi + GSBI_CONTROL_ADDR); if (pdata && pdata->config_gpio) { ret = gpio_request(pdata->uart_tx_gpio, "UART_TX_GPIO"); if (unlikely(ret)) { pr_err("%s: gpio request failed for:%d\n", __func__, pdata->uart_tx_gpio); return ret; } ret = gpio_request(pdata->uart_rx_gpio, "UART_RX_GPIO"); if (unlikely(ret)) { pr_err("%s: gpio request failed for:%d\n", __func__, pdata->uart_rx_gpio); gpio_free(pdata->uart_tx_gpio); return ret; } } } #ifndef CONFIG_PM_RUNTIME msm_hsl_init_clock(port); #endif pm_runtime_get_sync(port->dev); if (likely(port->fifosize > 12)) rfr_level = port->fifosize - 12; else rfr_level = port->fifosize; spin_lock_irqsave(&port->lock, flags); /* set automatic RFR level */ data = msm_hsl_read(port, UARTDM_MR1_ADDR); data &= ~UARTDM_MR1_AUTO_RFR_LEVEL1_BMSK; data &= ~UARTDM_MR1_AUTO_RFR_LEVEL0_BMSK; data |= UARTDM_MR1_AUTO_RFR_LEVEL1_BMSK & (rfr_level << 2); data |= UARTDM_MR1_AUTO_RFR_LEVEL0_BMSK & rfr_level; msm_hsl_write(port, data, UARTDM_MR1_ADDR); spin_unlock_irqrestore(&port->lock, flags); ret = request_irq(port->irq, msm_hsl_irq, IRQF_TRIGGER_HIGH, msm_hsl_port->name, port); if (unlikely(ret)) { printk(KERN_ERR "%s: failed to request_irq\n", __func__); return ret; } return 0; }
static void msm_hsl_set_baud_rate(struct uart_port *port, unsigned int baud) { unsigned int baud_code, rxstale, watermark; unsigned int data; struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port); switch (baud) { #ifdef CONFIG_LGE_FELICA case 300: baud_code = UARTDM_CSR_75; rxstale = 1; break; case 600: baud_code = UARTDM_CSR_150; rxstale = 1; break; case 1200: baud_code = UARTDM_CSR_300; rxstale = 1; break; case 2400: baud_code = UARTDM_CSR_600; rxstale = 1; break; case 4800: baud_code = UARTDM_CSR_1200; rxstale = 1; break; case 9600: baud_code = UARTDM_CSR_2400; rxstale = 2; break; case 14400: baud_code = UARTDM_CSR_3600; rxstale = 3; break; case 19200: baud_code = UARTDM_CSR_4800; rxstale = 4; break; case 28800: baud_code = UARTDM_CSR_7200; rxstale = 6; break; case 38400: baud_code = UARTDM_CSR_9600; rxstale = 8; break; case 57600: baud_code = UARTDM_CSR_14400; rxstale = 16; break; case 230400: baud_code = 0xee; rxstale = 31; break; case 460800: baud_code = 0xff; rxstale = 31; break; case 115200: default: baud_code = UARTDM_CSR_28800; rxstale = 31; break; #else case 300: baud_code = UARTDM_CSR_75; rxstale = 1; break; case 600: baud_code = UARTDM_CSR_150; rxstale = 1; break; case 1200: baud_code = UARTDM_CSR_300; rxstale = 1; break; case 2400: baud_code = UARTDM_CSR_600; rxstale = 1; break; case 4800: baud_code = UARTDM_CSR_1200; rxstale = 1; break; case 9600: baud_code = UARTDM_CSR_2400; rxstale = 2; break; case 14400: baud_code = UARTDM_CSR_3600; rxstale = 3; break; case 19200: baud_code = UARTDM_CSR_4800; rxstale = 4; break; case 28800: baud_code = UARTDM_CSR_7200; rxstale = 6; break; case 38400: baud_code = UARTDM_CSR_9600; rxstale = 8; break; case 57600: baud_code = UARTDM_CSR_14400; rxstale = 16; break; case 115200: baud_code = UARTDM_CSR_28800; rxstale = 31; break; case 230400: baud_code = UARTDM_CSR_57600; rxstale = 31; break; case 460800: baud_code = UARTDM_CSR_115200; rxstale = 31; break; default: /* 115200 baud rate */ baud_code = UARTDM_CSR_28800; rxstale = 31; break; #endif } msm_hsl_write(port, baud_code, UARTDM_CSR_ADDR); /* RX stale watermark */ watermark = UARTDM_IPR_STALE_LSB_BMSK & rxstale; watermark |= UARTDM_IPR_STALE_TIMEOUT_MSB_BMSK & (rxstale << 2); msm_hsl_write(port, watermark, UARTDM_IPR_ADDR); /* set RX watermark * Configure Rx Watermark as 3/4 size of Rx FIFO. * RFWR register takes value in Words for UARTDM Core * whereas it is consider to be in Bytes for UART Core. * Hence configuring Rx Watermark as 12 Words. */ watermark = (port->fifosize * 3) / (4 * 4); msm_hsl_write(port, watermark, UARTDM_RFWR_ADDR); /* set TX watermark */ msm_hsl_write(port, 0, UARTDM_TFWR_ADDR); msm_hsl_write(port, CR_PROTECTION_EN, UARTDM_CR_ADDR); msm_hsl_reset(port); data = UARTDM_CR_TX_EN_BMSK; data |= UARTDM_CR_RX_EN_BMSK; /* enable TX & RX */ msm_hsl_write(port, data, UARTDM_CR_ADDR); msm_hsl_write(port, RESET_STALE_INT, UARTDM_CR_ADDR); /* turn on RX and CTS interrupts */ msm_hsl_port->imr = UARTDM_ISR_RXSTALE_BMSK | UARTDM_ISR_DELTA_CTS_BMSK | UARTDM_ISR_RXLEV_BMSK; msm_hsl_write(port, msm_hsl_port->imr, UARTDM_IMR_ADDR); msm_hsl_write(port, 6500, UARTDM_DMRX_ADDR); msm_hsl_write(port, STALE_EVENT_ENABLE, UARTDM_CR_ADDR); }
static void handle_delta_cts(struct uart_port *port) { msm_hsl_write(port, RESET_CTS, UARTDM_CR_ADDR); port->icount.cts++; wake_up_interruptible(&port->state->port.delta_msr_wait); }
static void handle_tx(struct uart_port *port) { struct circ_buf *xmit = &port->state->xmit; int sent_tx; int tx_count; int x; unsigned int tf_pointer = 0; tx_count = uart_circ_chars_pending(xmit); if (tx_count > (UART_XMIT_SIZE - xmit->tail)) tx_count = UART_XMIT_SIZE - xmit->tail; if (tx_count >= port->fifosize) tx_count = port->fifosize; /* Handle x_char */ if (port->x_char) { wait_for_xmitr(port, UARTDM_ISR_TX_READY_BMSK); msm_hsl_write(port, tx_count + 1, UARTDM_NCF_TX_ADDR); msm_hsl_write(port, port->x_char, UARTDM_TF_ADDR); port->icount.tx++; port->x_char = 0; } else if (tx_count) { wait_for_xmitr(port, UARTDM_ISR_TX_READY_BMSK); msm_hsl_write(port, tx_count, UARTDM_NCF_TX_ADDR); } if (!tx_count) { msm_hsl_stop_tx(port); return; } #ifdef FELICA_DEBUG if (port->line == 3) pr_info("%s: count=%d\n", __func__, tx_count); #endif while (tf_pointer < tx_count) { if (unlikely(!(msm_hsl_read(port, UARTDM_SR_ADDR) & UARTDM_SR_TXRDY_BMSK))) continue; switch (tx_count - tf_pointer) { case 1: { x = xmit->buf[xmit->tail]; port->icount.tx++; break; } case 2: { x = xmit->buf[xmit->tail] | xmit->buf[xmit->tail+1] << 8; port->icount.tx += 2; break; } case 3: { x = xmit->buf[xmit->tail] | xmit->buf[xmit->tail+1] << 8 | xmit->buf[xmit->tail + 2] << 16; port->icount.tx += 3; break; } default: { x = *((int *)&(xmit->buf[xmit->tail])); port->icount.tx += 4; break; } } #ifdef FELICA_DEBUG if (port->line == 3) pr_info("%s: 0x%08X\n", __func__, x); #endif msm_hsl_write(port, x, UARTDM_TF_ADDR); xmit->tail = ((tx_count - tf_pointer < 4) ? (tx_count - tf_pointer + xmit->tail) : (xmit->tail + 4)) & (UART_XMIT_SIZE - 1); tf_pointer += 4; sent_tx = 1; } if (uart_circ_empty(xmit)) msm_hsl_stop_tx(port); if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(port); }
static void handle_rx(struct uart_port *port, unsigned int misr) { struct tty_struct *tty = port->state->port.tty; unsigned int sr; int count = 0; struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port); #ifdef FELICA_DEBUG if (port->line == 3) pr_info(">>> %s\n", __func__); #endif /* * Handle overrun. My understanding of the hardware is that overrun * is not tied to the RX buffer, so we handle the case out of band. */ if ((msm_hsl_read(port, UARTDM_SR_ADDR) & UARTDM_SR_OVERRUN_BMSK)) { #ifdef FELICA_DEBUG if (port->line == 3) pr_info("%s: UARTDM_SR_OVERRUN_BMSK\n", __func__); #endif port->icount.overrun++; tty_insert_flip_char(tty, 0, TTY_OVERRUN); msm_hsl_write(port, RESET_ERROR_STATUS, UARTDM_CR_ADDR); } if (misr & UARTDM_ISR_RXSTALE_BMSK) { #ifdef FELICA_DEBUG if (port->line == 3) { pr_info("%s: UARTDM_ISR_RXSTALE_BMSK\n", __func__); pr_info("%s: rx_total_snap = %u\n", __func__, msm_hsl_read(port, UARTDM_RX_TOTAL_SNAP_ADDR)); pr_info("%s: old_snap_state = %u\n", __func__, msm_hsl_port->old_snap_state); } #endif count = msm_hsl_read(port, UARTDM_RX_TOTAL_SNAP_ADDR) - msm_hsl_port->old_snap_state; msm_hsl_port->old_snap_state = 0; } else { #ifdef FELICA_DEBUG if (port->line == 3) { pr_info("%s: else...\n", __func__); pr_info("%s: rfwr = %u\n", __func__, msm_hsl_read(port, UARTDM_RFWR_ADDR)); pr_info("%s: old_snap_state = %u\n", __func__, msm_hsl_port->old_snap_state); } #endif count = 4 * (msm_hsl_read(port, UARTDM_RFWR_ADDR)); msm_hsl_port->old_snap_state += count; #ifdef FELICA_DEBUG if (port->line == 3) { pr_info("%s: old_snap_state = %u\n", __func__, msm_hsl_port->old_snap_state); } #endif } #ifdef FELICA_DEBUG if (port->line == 3) pr_info("%s: count=%d\n", __func__, count); #endif /* and now the main RX loop */ while (count > 0) { unsigned int c; char flag = TTY_NORMAL; sr = msm_hsl_read(port, UARTDM_SR_ADDR); if ((sr & UARTDM_SR_RXRDY_BMSK) == 0) { #ifdef FELICA_DEBUG if (port->line == 3) { pr_info("%s: UARTDM_SR_RXRDY_BMSK\n", __func__); pr_info("%s: old_snap_state = %u, count = %d\n", __func__, msm_hsl_port->old_snap_state, count); } #endif #ifdef CONFIG_LGE_FELICA if (msm_hsl_port->old_snap_state < count) msm_hsl_port->old_snap_state = 0; else #endif msm_hsl_port->old_snap_state -= count; break; } c = msm_hsl_read(port, UARTDM_RF_ADDR); #ifdef FELICA_DEBUG if (port->line == 3) pr_info("%s: [%d] 0x%08X\n", __func__, (count > 4) ? 4 : count, c); #endif if (sr & UARTDM_SR_RX_BREAK_BMSK) { #ifdef FELICA_DEBUG if (port->line == 3) pr_info("%s: UARTDM_SR_RX_BREAK_BMSK\n", __func__); #endif port->icount.brk++; if (uart_handle_break(port)) { #ifdef FELICA_DEBUG if (port->line == 3) pr_info("%s: uart_handle_break\n", __func__); #endif continue; } } else if (sr & UARTDM_SR_PAR_FRAME_BMSK) { #ifdef FELICA_DEBUG if (port->line == 3) pr_info("%s: UARTDM_SR_PAR_FRAME_BMSK\n", __func__); #endif port->icount.frame++; } else { #ifdef FELICA_DEBUG if (port->line == 3) pr_info("%s: RX\n", __func__); #endif port->icount.rx++; } /* Mask conditions we're ignorning. */ sr &= port->read_status_mask; if (sr & UARTDM_SR_RX_BREAK_BMSK) flag = TTY_BREAK; else if (sr & UARTDM_SR_PAR_FRAME_BMSK) flag = TTY_FRAME; /* TODO: handle sysrq */ /* if (!uart_handle_sysrq_char(port, c)) */ tty_insert_flip_string(tty, (char *) &c, (count > 4) ? 4 : count); count -= 4; } tty_flip_buffer_push(tty); #ifdef FELICA_DEBUG if (port->line == 3) pr_info("<<< %s\n", __func__); #endif }
static void msm_hsl_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { unsigned long flags; unsigned int baud, mr; spin_lock_irqsave(&port->lock, flags); clk_en(port, 1); /* calculate and set baud rate */ baud = uart_get_baud_rate(port, termios, old, 300, 115200); /* Workaround required for UART download feature. set_termios is getting called while opening port and while setting required baud rate using Ioctl. Adding delay allows this feature to work. Reason is still unknown. */ udelay(1000); msm_hsl_set_baud_rate(port, baud); /* calculate parity */ mr = msm_hsl_read(port, UARTDM_MR2_ADDR); mr &= ~UARTDM_MR2_PARITY_MODE_BMSK; if (termios->c_cflag & PARENB) { if (termios->c_cflag & PARODD) mr |= ODD_PARITY; else if (termios->c_cflag & CMSPAR) mr |= SPACE_PARITY; else mr |= EVEN_PARITY; } /* calculate bits per char */ mr &= ~UARTDM_MR2_BITS_PER_CHAR_BMSK; switch (termios->c_cflag & CSIZE) { case CS5: mr |= FIVE_BPC; break; case CS6: mr |= SIX_BPC; break; case CS7: mr |= SEVEN_BPC; break; case CS8: default: mr |= EIGHT_BPC; break; } /* calculate stop bits */ mr &= ~(STOP_BIT_ONE | STOP_BIT_TWO); if (termios->c_cflag & CSTOPB) mr |= STOP_BIT_TWO; else mr |= STOP_BIT_ONE; /* set parity, bits per char, and stop bit */ msm_hsl_write(port, mr, UARTDM_MR2_ADDR); /* calculate and set hardware flow control */ mr = msm_hsl_read(port, UARTDM_MR1_ADDR); mr &= ~(UARTDM_MR1_CTS_CTL_BMSK | UARTDM_MR1_RX_RDY_CTL_BMSK); if (termios->c_cflag & CRTSCTS) { mr |= UARTDM_MR1_CTS_CTL_BMSK; mr |= UARTDM_MR1_RX_RDY_CTL_BMSK; } msm_hsl_write(port, mr, UARTDM_MR1_ADDR); /* Configure status bits to ignore based on termio flags. */ port->read_status_mask = 0; if (termios->c_iflag & INPCK) port->read_status_mask |= UARTDM_SR_PAR_FRAME_BMSK; if (termios->c_iflag & (BRKINT | PARMRK)) port->read_status_mask |= UARTDM_SR_RX_BREAK_BMSK; uart_update_timeout(port, termios->c_cflag, baud); clk_en(port, 0); spin_unlock_irqrestore(&port->lock, flags); }
static int msm_hsl_startup(struct uart_port *port) { struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port); unsigned int data, rfr_level; int ret; unsigned long flags; snprintf(msm_hsl_port->name, sizeof(msm_hsl_port->name), "msm_serial_hsl%d", port->line); #ifndef CONFIG_PM_RUNTIME msm_hsl_init_clock(port); #endif pm_runtime_get_sync(port->dev); if (likely(port->fifosize > 12)) rfr_level = port->fifosize - 12; else rfr_level = port->fifosize; spin_lock_irqsave(&port->lock, flags); /* set automatic RFR level */ data = msm_hsl_read(port, UARTDM_MR1_ADDR); data &= ~UARTDM_MR1_AUTO_RFR_LEVEL1_BMSK; data &= ~UARTDM_MR1_AUTO_RFR_LEVEL0_BMSK; data |= UARTDM_MR1_AUTO_RFR_LEVEL1_BMSK & (rfr_level << 2); data |= UARTDM_MR1_AUTO_RFR_LEVEL0_BMSK & rfr_level; msm_hsl_write(port, data, UARTDM_MR1_ADDR); /* Make sure IPR is not 0 to start with*/ msm_hsl_write(port, UARTDM_IPR_STALE_LSB_BMSK, UARTDM_IPR_ADDR); data = 0; if (!(is_console(port)) || (!port->cons) || (port->cons && (!(port->cons->flags & CON_ENABLED)))) { msm_hsl_write(port, CR_PROTECTION_EN, UARTDM_CR_ADDR); msm_hsl_write(port, UARTDM_MR2_BITS_PER_CHAR_8 | STOP_BIT_ONE, UARTDM_MR2_ADDR); /* 8N1 */ msm_hsl_reset(port); data = UARTDM_CR_TX_EN_BMSK; } if(b_terminal_onoff == 0 && console_uart_port && (port == console_uart_port)){ msm_hsl_write(port, data, UARTDM_CR_ADDR); /* enable TX */ }else{ data |= UARTDM_CR_RX_EN_BMSK; msm_hsl_write(port, data, UARTDM_CR_ADDR); /* enable TX & RX */ } /* turn on RX and CTS interrupts */ msm_hsl_port->imr = UARTDM_ISR_RXSTALE_BMSK | UARTDM_ISR_DELTA_CTS_BMSK | UARTDM_ISR_RXLEV_BMSK; spin_unlock_irqrestore(&port->lock, flags); ret = request_irq(port->irq, msm_hsl_irq, IRQF_TRIGGER_HIGH, msm_hsl_port->name, port); if (unlikely(ret)) { printk(KERN_ERR "%s: failed to request_irq\n", __func__); return ret; } spin_lock_irqsave(&port->lock, flags); msm_hsl_write(port, RESET_STALE_INT, UARTDM_CR_ADDR); msm_hsl_write(port, 6500, UARTDM_DMRX_ADDR); msm_hsl_write(port, STALE_EVENT_ENABLE, UARTDM_CR_ADDR); msm_hsl_write(port, msm_hsl_port->imr, UARTDM_IMR_ADDR); spin_unlock_irqrestore(&port->lock, flags); return 0; }
static void msm_hsl_set_baud_rate(struct uart_port *port, unsigned int baud) { unsigned int baud_code, rxstale, watermark; /* Since requested clock rate is 4 times the clock rate assumed for CSR calculation, the CSR should programmed with 1/4th the requested baud rate */ switch (baud) { case 300: baud_code = UARTDM_CSR_75; rxstale = 1; break; case 600: baud_code = UARTDM_CSR_150; rxstale = 1; break; case 1200: baud_code = UARTDM_CSR_300; rxstale = 1; break; case 2400: baud_code = UARTDM_CSR_600; rxstale = 1; break; case 4800: baud_code = UARTDM_CSR_1200; rxstale = 1; break; case 9600: baud_code = UARTDM_CSR_2400; rxstale = 2; break; case 14400: baud_code = UARTDM_CSR_3600; rxstale = 3; break; case 19200: baud_code = UARTDM_CSR_4800; rxstale = 4; break; case 28800: baud_code = UARTDM_CSR_7200; rxstale = 6; break; case 38400: baud_code = UARTDM_CSR_9600; rxstale = 8; break; case 57600: baud_code = UARTDM_CSR_14400; rxstale = 16; break; case 115200: default: baud_code = UARTDM_CSR_28800; rxstale = 31; break; } msm_hsl_write(port, baud_code, UARTDM_CSR_ADDR); /* RX stale watermark */ watermark = UARTDM_IPR_STALE_LSB_BMSK & rxstale; watermark |= UARTDM_IPR_STALE_TIMEOUT_MSB_BMSK & (rxstale << 2); msm_hsl_write(port, watermark, UARTDM_IPR_ADDR); /* set RX watermark */ watermark = (port->fifosize * 3) / 4; msm_hsl_write(port, watermark, UARTDM_RFWR_ADDR); /* set TX watermark */ msm_hsl_write(port, 0, UARTDM_TFWR_ADDR); }
static void handle_rx(struct uart_port *port, unsigned int misr) { struct tty_struct *tty = port->state->port.tty; unsigned int sr; int count = 0; struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port); /* * Handle overrun. My understanding of the hardware is that overrun * is not tied to the RX buffer, so we handle the case out of band. */ if ((msm_hsl_read(port, UARTDM_SR_ADDR) & UARTDM_SR_OVERRUN_BMSK)) { port->icount.overrun++; tty_insert_flip_char(tty, 0, TTY_OVERRUN); msm_hsl_write(port, RESET_ERROR_STATUS, UARTDM_CR_ADDR); } if (misr & UARTDM_ISR_RXSTALE_BMSK) { count = msm_hsl_read(port, UARTDM_RX_TOTAL_SNAP_ADDR) - msm_hsl_port->old_snap_state; msm_hsl_port->old_snap_state = 0; } else { count = 4 * (msm_hsl_read(port, UARTDM_RFWR_ADDR)); msm_hsl_port->old_snap_state += count; } /* and now the main RX loop */ while (count > 0) { unsigned int c; char flag = TTY_NORMAL; sr = msm_hsl_read(port, UARTDM_SR_ADDR); if ((sr & UARTDM_SR_RXRDY_BMSK) == 0) { msm_hsl_port->old_snap_state -= count; break; } c = msm_hsl_read(port, UARTDM_RF_ADDR); if (sr & UARTDM_SR_RX_BREAK_BMSK) { port->icount.brk++; if (uart_handle_break(port)) continue; } else if (sr & UARTDM_SR_PAR_FRAME_BMSK) { port->icount.frame++; } else { port->icount.rx++; } /* Mask conditions we're ignorning. */ sr &= port->read_status_mask; if (sr & UARTDM_SR_RX_BREAK_BMSK) flag = TTY_BREAK; else if (sr & UARTDM_SR_PAR_FRAME_BMSK) flag = TTY_FRAME; /* TODO: handle sysrq */ /* if (!uart_handle_sysrq_char(port, c)) */ tty_insert_flip_string(tty, (char *) &c, (count > 4) ? 4 : count); count -= 4; } tty_flip_buffer_push(tty); }