--- zzzz-none-000/linux-4.4.60/drivers/tty/serial/msm_serial.c 2017-04-08 07:53:53.000000000 +0000 +++ dragonfly-4020-701/linux-4.4.60/drivers/tty/serial/msm_serial.c 2018-11-08 13:36:17.000000000 +0000 @@ -19,33 +19,148 @@ # define SUPPORT_SYSRQ #endif +#include #include #include #include -#include #include #include #include -#include +#include #include #include #include #include #include -#include #include #include #include #include #include #include +#include -#include "msm_serial.h" +#define UART_MR1 0x0000 + +#define UART_MR1_AUTO_RFR_LEVEL0 0x3F +#define UART_MR1_AUTO_RFR_LEVEL1 0x3FF00 +#define UART_DM_MR1_AUTO_RFR_LEVEL1 0xFFFFFF00 +#define UART_MR1_RX_RDY_CTL BIT(7) +#define UART_MR1_CTS_CTL BIT(6) + +#define UART_MR2 0x0004 +#define UART_MR2_ERROR_MODE BIT(6) +#define UART_MR2_BITS_PER_CHAR 0x30 +#define UART_MR2_BITS_PER_CHAR_5 (0x0 << 4) +#define UART_MR2_BITS_PER_CHAR_6 (0x1 << 4) +#define UART_MR2_BITS_PER_CHAR_7 (0x2 << 4) +#define UART_MR2_BITS_PER_CHAR_8 (0x3 << 4) +#define UART_MR2_STOP_BIT_LEN_ONE (0x1 << 2) +#define UART_MR2_STOP_BIT_LEN_TWO (0x3 << 2) +#define UART_MR2_PARITY_MODE_NONE 0x0 +#define UART_MR2_PARITY_MODE_ODD 0x1 +#define UART_MR2_PARITY_MODE_EVEN 0x2 +#define UART_MR2_PARITY_MODE_SPACE 0x3 +#define UART_MR2_PARITY_MODE 0x3 + +#define UART_CSR 0x0008 + +#define UART_TF 0x000C +#define UARTDM_TF 0x0070 + +#define UART_CR 0x0010 +#define UART_CR_CMD_NULL (0 << 4) +#define UART_CR_CMD_RESET_RX (1 << 4) +#define UART_CR_CMD_RESET_TX (2 << 4) +#define UART_CR_CMD_RESET_ERR (3 << 4) +#define UART_CR_CMD_RESET_BREAK_INT (4 << 4) +#define UART_CR_CMD_START_BREAK (5 << 4) +#define UART_CR_CMD_STOP_BREAK (6 << 4) +#define UART_CR_CMD_RESET_CTS (7 << 4) +#define UART_CR_CMD_RESET_STALE_INT (8 << 4) +#define UART_CR_CMD_PACKET_MODE (9 << 4) +#define UART_CR_CMD_MODE_RESET (12 << 4) +#define UART_CR_CMD_SET_RFR (13 << 4) +#define UART_CR_CMD_RESET_RFR (14 << 4) +#define UART_CR_CMD_PROTECTION_EN (16 << 4) +#define UART_CR_CMD_STALE_EVENT_DISABLE (6 << 8) +#define UART_CR_CMD_STALE_EVENT_ENABLE (80 << 4) +#define UART_CR_CMD_FORCE_STALE (4 << 8) +#define UART_CR_CMD_RESET_TX_READY (3 << 8) +#define UART_CR_TX_DISABLE BIT(3) +#define UART_CR_TX_ENABLE BIT(2) +#define UART_CR_RX_DISABLE BIT(1) +#define UART_CR_RX_ENABLE BIT(0) +#define UART_CR_CMD_RESET_RXBREAK_START ((1 << 11) | (2 << 4)) + +#define UART_IMR 0x0014 +#define UART_IMR_TXLEV BIT(0) +#define UART_IMR_RXSTALE BIT(3) +#define UART_IMR_RXLEV BIT(4) +#define UART_IMR_DELTA_CTS BIT(5) +#define UART_IMR_CURRENT_CTS BIT(6) +#define UART_IMR_RXBREAK_START BIT(10) + +#define UART_IPR_RXSTALE_LAST 0x20 +#define UART_IPR_STALE_LSB 0x1F +#define UART_IPR_STALE_TIMEOUT_MSB 0x3FF80 +#define UART_DM_IPR_STALE_TIMEOUT_MSB 0xFFFFFF80 + +#define UART_IPR 0x0018 +#define UART_TFWR 0x001C +#define UART_RFWR 0x0020 +#define UART_HCR 0x0024 + +#define UART_MREG 0x0028 +#define UART_NREG 0x002C +#define UART_DREG 0x0030 +#define UART_MNDREG 0x0034 +#define UART_IRDA 0x0038 +#define UART_MISR_MODE 0x0040 +#define UART_MISR_RESET 0x0044 +#define UART_MISR_EXPORT 0x0048 +#define UART_MISR_VAL 0x004C +#define UART_TEST_CTRL 0x0050 + +#define UART_SR 0x0008 +#define UART_SR_HUNT_CHAR BIT(7) +#define UART_SR_RX_BREAK BIT(6) +#define UART_SR_PAR_FRAME_ERR BIT(5) +#define UART_SR_OVERRUN BIT(4) +#define UART_SR_TX_EMPTY BIT(3) +#define UART_SR_TX_READY BIT(2) +#define UART_SR_RX_FULL BIT(1) +#define UART_SR_RX_READY BIT(0) + +#define UART_RF 0x000C +#define UARTDM_RF 0x0070 +#define UART_MISR 0x0010 +#define UART_ISR 0x0014 +#define UART_ISR_TX_READY BIT(7) + +#define UARTDM_RXFS 0x50 +#define UARTDM_RXFS_BUF_SHIFT 0x7 +#define UARTDM_RXFS_BUF_MASK 0x7 + +#define UARTDM_DMEN 0x3C +#define UARTDM_DMEN_RX_SC_ENABLE BIT(5) +#define UARTDM_DMEN_TX_SC_ENABLE BIT(4) + +#define UARTDM_DMEN_TX_BAM_ENABLE BIT(2) /* UARTDM_1P4 */ +#define UARTDM_DMEN_TX_DM_ENABLE BIT(0) /* < UARTDM_1P4 */ + +#define UARTDM_DMEN_RX_BAM_ENABLE BIT(3) /* UARTDM_1P4 */ +#define UARTDM_DMEN_RX_DM_ENABLE BIT(1) /* < UARTDM_1P4 */ + +#define UARTDM_DMRX 0x34 +#define UARTDM_NCF_TX 0x40 +#define UARTDM_RX_TOTAL_SNAP 0x38 + +#define UARTDM_BURST_SIZE 16 /* in bytes */ +#define UARTDM_TX_AIGN(x) ((x) & ~0x3) /* valid for > 1p3 */ +#define UARTDM_TX_MAX 256 /* in bytes, valid for <= 1p3 */ +#define UARTDM_RX_SIZE (UART_XMIT_SIZE / 4) -#define UARTDM_BURST_SIZE 16 /* in bytes */ -#define UARTDM_TX_AIGN(x) ((x) & ~0x3) /* valid for > 1p3 */ -#define UARTDM_TX_MAX 256 /* in bytes, valid for <= 1p3 */ -#define UARTDM_RX_SIZE (UART_XMIT_SIZE / 4) enum { UARTDM_1P1 = 1, @@ -78,10 +193,76 @@ struct msm_dma rx_dma; }; +#if defined(CONFIG_AVM_ENHANCED) +#include "msm_dectuart.h" + +static int msm_serial_dectuart_get_char(void); +static void msm_serial_dectuart_put_char(unsigned char ch); +static void msm_serial_dectuart_init(unsigned int baud, int mode); +static void msm_serial_dectuart_exit(void); +static void msm_serial_console_stop(void); +static void msm_serial_console_start(void); +#endif/*--- #if defined(CONFIG_AVM_ENHANCED) ---*/ + +#define UART_TO_MSM(uart_port) container_of(uart_port, struct msm_port, uart) + +static +void msm_write(struct uart_port *port, unsigned int val, unsigned int off) +{ + writel_relaxed(val, port->membase + off); +} + +static +unsigned int msm_read(struct uart_port *port, unsigned int off) +{ + return readl_relaxed(port->membase + off); +} + +/* + * Setup the MND registers to use the TCXO clock. + */ +static void msm_serial_set_mnd_regs_tcxo(struct uart_port *port) +{ + msm_write(port, 0x06, UART_MREG); + msm_write(port, 0xF1, UART_NREG); + msm_write(port, 0x0F, UART_DREG); + msm_write(port, 0x1A, UART_MNDREG); + port->uartclk = 1843200; +} + +/* + * Setup the MND registers to use the TCXO clock divided by 4. + */ +static void msm_serial_set_mnd_regs_tcxoby4(struct uart_port *port) +{ + msm_write(port, 0x18, UART_MREG); + msm_write(port, 0xF6, UART_NREG); + msm_write(port, 0x0F, UART_DREG); + msm_write(port, 0x0A, UART_MNDREG); + port->uartclk = 1843200; +} + +static void msm_serial_set_mnd_regs(struct uart_port *port) +{ + struct msm_port *msm_port = UART_TO_MSM(port); + + /* + * These registers don't exist so we change the clk input rate + * on uartdm hardware instead + */ + if (msm_port->is_uartdm) + return; + + if (port->uartclk == 19200000) + msm_serial_set_mnd_regs_tcxo(port); + else if (port->uartclk == 4800000) + msm_serial_set_mnd_regs_tcxoby4(port); +} + static void msm_handle_tx(struct uart_port *port); static void msm_start_rx_dma(struct msm_port *msm_port); -void msm_stop_dma(struct uart_port *port, struct msm_dma *dma) +static void msm_stop_dma(struct uart_port *port, struct msm_dma *dma) { struct device *dev = port->dev; unsigned int mapped; @@ -243,6 +424,11 @@ struct msm_port *msm_port = UART_TO_MSM(port); struct msm_dma *dma = &msm_port->tx_dma; +#if defined(CONFIG_AVM_ENHANCED) + if(msm_dectuart_is_open(&msm_dectuart)) { + return; + } +#endif/*--- #if defined(CONFIG_AVM_ENHANCED) ---*/ /* Already started in DMA mode */ if (dma->count) return; @@ -388,10 +574,6 @@ val &= ~dma->enable_bit; msm_write(port, val, UARTDM_DMEN); - /* Restore interrupts */ - msm_port->imr |= UART_IMR_RXLEV | UART_IMR_RXSTALE; - msm_write(port, msm_port->imr, UART_IMR); - if (msm_read(port, UART_SR) & UART_SR_OVERRUN) { port->icount.overrun++; tty_insert_flip_char(tport, 0, TTY_OVERRUN); @@ -526,8 +708,11 @@ { struct tty_port *tport = &port->state->port; unsigned int sr; + int sysrq, r_count, i; int count = 0; struct msm_port *msm_port = UART_TO_MSM(port); + unsigned int reg_buf; + unsigned char *buf = (unsigned char *)®_buf; if ((msm_read(port, UART_SR) & UART_SR_OVERRUN)) { port->icount.overrun++; @@ -549,9 +734,6 @@ port->icount.rx += count; while (count > 0) { - unsigned char buf[4]; - int sysrq, r_count, i; - sr = msm_read(port, UART_SR); if ((sr & UART_SR_RX_READY) == 0) { msm_port->old_snap_state -= count; @@ -559,7 +741,7 @@ } ioread32_rep(port->membase + UARTDM_RF, buf, 1); - r_count = min_t(int, count, sizeof(buf)); + r_count = min_t(int, count, sizeof(reg_buf)); for (i = 0; i < r_count; i++) { char flag = TTY_NORMAL; @@ -575,6 +757,13 @@ if (!(port->read_status_mask & UART_SR_RX_BREAK)) flag = TTY_NORMAL; +#if defined(CONFIG_AVM_ENHANCED) + if(msm_dectuart_is_open(&msm_dectuart)) { + msm_dectuart_pipe_enqueue(&msm_dectuart, buf[i]); + continue; + } +#endif/*--- #if defined(CONFIG_AVM_ENHANCED) ---*/ + spin_unlock(&port->lock); sysrq = uart_handle_sysrq_char(port, buf[i]); spin_lock(&port->lock); @@ -657,6 +846,9 @@ unsigned int num_chars; unsigned int tf_pointer = 0; void __iomem *tf; + int i; + unsigned int reg_buf; + unsigned char *buf = (unsigned char *)®_buf; if (msm_port->is_uartdm) tf = port->membase + UARTDM_TF; @@ -667,15 +859,14 @@ msm_reset_dm_count(port, tx_count); while (tf_pointer < tx_count) { - int i; - char buf[4] = { 0 }; + reg_buf = 0; if (!(msm_read(port, UART_SR) & UART_SR_TX_READY)) break; if (msm_port->is_uartdm) num_chars = min(tx_count - tf_pointer, - (unsigned int)sizeof(buf)); + (unsigned int)sizeof(reg_buf)); else num_chars = 1; @@ -704,8 +895,13 @@ struct msm_dma *dma = &msm_port->tx_dma; unsigned int pio_count, dma_count, dma_min; void __iomem *tf; + unsigned int reg_buf; int err = 0; - +#if defined(CONFIG_AVM_ENHANCED) + if(msm_dectuart_is_open(&msm_dectuart)) { + return; + } +#endif/*--- #if defined(CONFIG_AVM_ENHANCED) ---*/ if (port->x_char) { if (msm_port->is_uartdm) tf = port->membase + UARTDM_TF; @@ -715,7 +911,8 @@ if (msm_port->is_uartdm) msm_reset_dm_count(port, 1); - iowrite8_rep(tf, &port->x_char, 1); + reg_buf = port->x_char; + iowrite32_rep(tf, ®_buf, 1); port->icount.tx++; port->x_char = 0; return; @@ -785,7 +982,12 @@ * Flush DMA input fifo to memory, this will also * trigger DMA RX completion */ - dmaengine_terminate_all(dma->chan); + if (msm_port->is_uartdm < UARTDM_1P4) { + dmaengine_terminate_all_graceful(dma->chan, + true); + } else { + dmaengine_terminate_all(dma->chan); + } } else if (msm_port->is_uartdm) { msm_handle_rx_dm(port, misr); } else { @@ -813,13 +1015,16 @@ return TIOCM_CAR | TIOCM_CTS | TIOCM_DSR | TIOCM_RTS; } -static void msm_reset(struct uart_port *port) +static void msm_reset(struct uart_port *port, bool reset_tx) { struct msm_port *msm_port = UART_TO_MSM(port); /* reset everything */ msm_write(port, UART_CR_CMD_RESET_RX, UART_CR); - msm_write(port, UART_CR_CMD_RESET_TX, UART_CR); + + if (reset_tx) + msm_write(port, UART_CR_CMD_RESET_TX, UART_CR); + msm_write(port, UART_CR_CMD_RESET_ERR, UART_CR); msm_write(port, UART_CR_CMD_RESET_BREAK_INT, UART_CR); msm_write(port, UART_CR_CMD_RESET_CTS, UART_CR); @@ -861,37 +1066,72 @@ }; static const struct msm_baud_map * -msm_find_best_baud(struct uart_port *port, unsigned int baud) +msm_find_best_baud(struct uart_port *port, unsigned int baud, + unsigned long *rate) { - unsigned int i, divisor; - const struct msm_baud_map *entry; + struct msm_port *msm_port = UART_TO_MSM(port); + unsigned int divisor, result; + unsigned long target, old, best_rate = 0, diff, best_diff = ULONG_MAX; + const struct msm_baud_map *entry, *end, *best; static const struct msm_baud_map table[] = { - { 1536, 0x00, 1 }, - { 768, 0x11, 1 }, - { 384, 0x22, 1 }, - { 192, 0x33, 1 }, - { 96, 0x44, 1 }, - { 48, 0x55, 1 }, - { 32, 0x66, 1 }, - { 24, 0x77, 1 }, - { 16, 0x88, 1 }, - { 12, 0x99, 6 }, - { 8, 0xaa, 6 }, - { 6, 0xbb, 6 }, - { 4, 0xcc, 6 }, - { 3, 0xdd, 8 }, - { 2, 0xee, 16 }, { 1, 0xff, 31 }, - { 0, 0xff, 31 }, + { 2, 0xee, 16 }, + { 3, 0xdd, 8 }, + { 4, 0xcc, 6 }, + { 6, 0xbb, 6 }, + { 8, 0xaa, 6 }, + { 12, 0x99, 6 }, + { 16, 0x88, 1 }, + { 24, 0x77, 1 }, + { 32, 0x66, 1 }, + { 48, 0x55, 1 }, + { 96, 0x44, 1 }, + { 192, 0x33, 1 }, + { 384, 0x22, 1 }, + { 768, 0x11, 1 }, + { 1536, 0x00, 1 }, }; - divisor = uart_get_divisor(port, baud); + best = table; /* Default to smallest divider */ + target = clk_round_rate(msm_port->clk, 16 * baud); + divisor = DIV_ROUND_CLOSEST(target, 16 * baud); + + end = table + ARRAY_SIZE(table); + entry = table; + while (entry < end) { + if (entry->divisor <= divisor) { + result = target / entry->divisor / 16; + diff = abs(result - baud); + + /* Keep track of best entry */ + if (diff < best_diff) { + best_diff = diff; + best = entry; + best_rate = target; + } - for (i = 0, entry = table; i < ARRAY_SIZE(table); i++, entry++) - if (entry->divisor <= divisor) - break; + if (result == baud) + break; + } else if (entry->divisor > divisor) { + old = target; + target = clk_round_rate(msm_port->clk, old + 1); + /* + * The rate didn't get any faster so we can't do + * better at dividing it down + */ + if (target == old) + break; + + /* Start the divisor search over at this new rate */ + entry = table; + divisor = DIV_ROUND_CLOSEST(target, 16 * baud); + continue; + } + entry++; + } - return entry; /* Default to smallest divider */ + *rate = best_rate; + return best; } static int msm_set_baud_rate(struct uart_port *port, unsigned int baud, @@ -900,22 +1140,20 @@ unsigned int rxstale, watermark, mask; struct msm_port *msm_port = UART_TO_MSM(port); const struct msm_baud_map *entry; - unsigned long flags; - - entry = msm_find_best_baud(port, baud); - - msm_write(port, entry->code, UART_CSR); - - if (baud > 460800) - port->uartclk = baud * 16; + unsigned long flags, rate; flags = *saved_flags; spin_unlock_irqrestore(&port->lock, flags); - clk_set_rate(msm_port->clk, port->uartclk); + entry = msm_find_best_baud(port, baud, &rate); + clk_set_rate(msm_port->clk, rate); + baud = rate / 16 / entry->divisor; spin_lock_irqsave(&port->lock, flags); *saved_flags = flags; + port->uartclk = rate; + + msm_write(port, entry->code, UART_CSR); /* RX stale watermark */ rxstale = entry->rxstale; @@ -939,7 +1177,13 @@ msm_write(port, 10, UART_TFWR); msm_write(port, UART_CR_CMD_PROTECTION_EN, UART_CR); - msm_reset(port); + + /* + * Check for console in this port and don't do TX reset + * if console is enabled in this port. + */ + msm_reset(port, !(uart_console(port) && + (port->cons->flags & CON_ENABLED))); /* Enable RX and TX */ msm_write(port, UART_CR_TX_ENABLE | UART_CR_RX_ENABLE, UART_CR); @@ -1252,7 +1496,7 @@ return c; } -static int msm_poll_get_char(struct uart_port *port) +static int msm_poll_get_char(struct uart_port *port) { u32 imr; int c; @@ -1272,7 +1516,9 @@ return c; } +#endif +#if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_AVM_ENHANCED) static void msm_poll_put_char(struct uart_port *port, unsigned char c) { u32 imr; @@ -1299,7 +1545,7 @@ /* Enable interrupts */ msm_write(port, imr, UART_IMR); } -#endif +#endif/*--- #if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_AVM_ENHANCED) ---*/ static struct uart_ops msm_uart_pops = { .tx_empty = msm_tx_empty, @@ -1366,10 +1612,15 @@ static void __msm_console_write(struct uart_port *port, const char *s, unsigned int count, bool is_uartdm) { - int i; + int i, j; int num_newlines = 0; bool replaced = false; void __iomem *tf; + struct msm_port *msm_port = UART_TO_MSM(port); + struct msm_dma *dma = &msm_port->tx_dma; + unsigned int num_chars; + unsigned int reg_buf; + unsigned char *buf = (unsigned char *)®_buf; if (is_uartdm) tf = port->membase + UARTDM_TF; @@ -1383,17 +1634,26 @@ count += num_newlines; spin_lock(&port->lock); + + /* + * If any TX DMA operation is ongoing in BAM DMA then console write + * can not be used since it uses the FIFO mode. + */ + if (dma->count) { + spin_unlock(&port->lock); + return; + } + if (is_uartdm) msm_reset_dm_count(port, count); i = 0; while (i < count) { - int j; - unsigned int num_chars; - char buf[4] = { 0 }; + reg_buf = 0; if (is_uartdm) - num_chars = min(count - i, (unsigned int)sizeof(buf)); + num_chars = min(count - i, + (unsigned int)sizeof(reg_buf)); else num_chars = 1; @@ -1478,7 +1738,6 @@ device->con->write = msm_serial_early_write; return 0; } -EARLYCON_DECLARE(msm_serial, msm_serial_early_console_setup); OF_EARLYCON_DECLARE(msm_serial, "qcom,msm-uart", msm_serial_early_console_setup); @@ -1500,7 +1759,6 @@ device->con->write = msm_serial_early_write_dm; return 0; } -EARLYCON_DECLARE(msm_serial_dm, msm_serial_early_console_setup_dm); OF_EARLYCON_DECLARE(msm_serial_dm, "qcom,msm-uartdm", msm_serial_early_console_setup_dm); @@ -1547,6 +1805,8 @@ struct uart_port *port; const struct of_device_id *id; int irq, line; + u32 serial_clk; + int ret; if (pdev->dev.of_node) line = of_alias_get_id(pdev->dev.of_node, "serial"); @@ -1564,6 +1824,17 @@ port = msm_get_port_from_line(line); port->dev = &pdev->dev; msm_port = UART_TO_MSM(port); +#if defined(CONFIG_AVM_ENHANCED) + pr_info("%s: set dectuart_port to ttyMSM%d\n", __func__, line); + msm_dectuart.port = port; + msm_dectuart.msm_dectuart_get_char = msm_serial_dectuart_get_char; + msm_dectuart.msm_dectuart_put_char = msm_serial_dectuart_put_char; + msm_dectuart.msm_dectuart_init = msm_serial_dectuart_init; + msm_dectuart.msm_console_stop = msm_serial_console_stop; + msm_dectuart.msm_console_start = msm_serial_console_start; + msm_dectuart.msm_dectuart_exit = msm_serial_dectuart_exit; +#endif/*--- #if defined(CONFIG_AVM_ENHANCED) ---*/ + id = of_match_device(msm_uartdm_table, &pdev->dev); if (id) @@ -1579,8 +1850,17 @@ msm_port->pclk = devm_clk_get(&pdev->dev, "iface"); if (IS_ERR(msm_port->pclk)) return PTR_ERR(msm_port->pclk); + } - clk_set_rate(msm_port->clk, 1843200); + /* Setting the clock only if defined in the dts */ + if (!of_property_read_u32(pdev->dev.of_node, "serial_clk", + &serial_clk)) { + ret = clk_set_rate(msm_port->clk, serial_clk); + if (ret) { + dev_err(&pdev->dev, "clk set rate failed (%d) for %u\n", + ret, serial_clk); + return ret; + } } port->uartclk = clk_get_rate(msm_port->clk); @@ -1633,7 +1913,7 @@ ret = uart_register_driver(&msm_uart_driver); if (unlikely(ret)) return ret; - + ret = platform_driver_register(&msm_platform_driver); if (unlikely(ret)) uart_unregister_driver(&msm_uart_driver); @@ -1649,6 +1929,169 @@ uart_unregister_driver(&msm_uart_driver); } +#if defined(CONFIG_AVM_ENHANCED) +/**--------------------------------------------------------------------------------**\ +\**--------------------------------------------------------------------------------**/ +static __maybe_unused void dump_msm_regs(const char *prefix, struct uart_port *port) { + unsigned int sr, isr, misr, mr1, mr2, ncf, rxfs, ts; + + sr = msm_read(port, UART_SR); + isr = msm_read(port, UART_ISR); + misr = msm_read(port, UART_MISR); + mr1 = msm_read(port, UART_MR1); + mr2 = msm_read(port, UART_MR2); + ncf = msm_read(port, UARTDM_NCF_TX); + rxfs = msm_read(port, UARTDM_RXFS); + ts = msm_read(port, UARTDM_RX_TOTAL_SNAP); + + pr_info("%s:\n", prefix); + pr_info("SR: %08x\n", sr); + pr_info("ISR: %08x\n", isr); + pr_info("MISR: %08x\n", misr); + pr_info("MR1: %08x\n", mr1); + pr_info("MR2: %08x\n", mr2); + pr_info("NCF: %08x\n", ncf); + pr_info("RXFS: %08x\n", rxfs); + pr_info("TS: %08x\n", ts); +} +/**--------------------------------------------------------------------------------**\ +\**--------------------------------------------------------------------------------**/ +static void msm_dectuart_dm_save(struct _msm_dectuart *pdectuart) { + struct uart_port *port = pdectuart->port; + /*--- dump_msm_regs(__func__, port); ---*/ + pdectuart->mr1 = msm_read(port, UART_MR1); + pdectuart->mr2 = msm_read(port, UART_MR2); +} +/**--------------------------------------------------------------------------------**\ +\**--------------------------------------------------------------------------------**/ +static void msm_dectuart_dm_restore(struct _msm_dectuart *pdectuart) { + struct uart_port *port = pdectuart->port; + struct msm_port *msm_port = UART_TO_MSM(port); + /*--- pr_info("%s\n", __func__); ---*/ + + msm_write(port, pdectuart->mr1, UART_MR1); + msm_write(port, pdectuart->mr2, UART_MR2); + msm_write(port, msm_port->imr, UART_IMR); +} +/**--------------------------------------------------------------------------------**\ + 8-N-1 configuration: 8 data bits - No parity - 1 stop bit + an no hw-flowcontrol +\**--------------------------------------------------------------------------------**/ +static void msm_dectuart_dm_init(struct _msm_dectuart *pdectuart) { + struct uart_port *port = pdectuart->port; + unsigned int mr; + /*--- pr_info("%s\n", __func__); ---*/ + /* no Hardware flow control */ + mr = msm_read(port, UART_MR1); + mr &= ~(UART_MR1_CTS_CTL | UART_MR1_RX_RDY_CTL); + msm_write(port, mr, UART_MR1); + + mr = msm_read(port, UART_MR2); + /* no parity */ + mr &= ~UART_MR2_PARITY_MODE; + /* CS8 */ + mr &= ~UART_MR2_BITS_PER_CHAR; + mr |= UART_MR2_BITS_PER_CHAR_8; + /* 1 stop bits */ + mr &= ~(UART_MR2_STOP_BIT_LEN_ONE | UART_MR2_STOP_BIT_LEN_TWO); + mr |= UART_MR2_STOP_BIT_LEN_ONE; + + /* set parity, bits per char, and stop bit */ + msm_write(port, mr, UART_MR2); +} +/**--------------------------------------------------------------------------------**\ +\**--------------------------------------------------------------------------------**/ +static int msm_serial_dectuart_get_char(void){ + struct _msm_dectuart *pdectuart = &msm_dectuart; + int c; + if(!pdectuart->port){ + return -ENXIO; + } + c = msm_dectuart_pipe_dequeue(pdectuart); + if(c == -1) { + return -EAGAIN; + } + return c; + return -EAGAIN; +} +/**--------------------------------------------------------------------------------**\ +\**--------------------------------------------------------------------------------**/ +static void msm_serial_dectuart_put_char(unsigned char ch){ + struct uart_port *port = msm_dectuart.port; + if(port == NULL){ + return; + } + msm_poll_put_char(port, ch); +} +/**--------------------------------------------------------------------------------**\ + * mode: != 0 und Tx/Rx-Irq an +\**--------------------------------------------------------------------------------**/ +static void msm_serial_dectuart_init(unsigned int baud, int mode){ + struct _msm_dectuart *pdectuart = &msm_dectuart; + struct uart_port *port = pdectuart->port; + unsigned long flags; + if(port == NULL){ + return; + } + /*--- pr_info("%s: dect_baud=%u %s\n", __func__, baud, !mode ? "pollmode" : ""); ---*/ + /*--- dump_msm_regs(__func__, port); ---*/ + if(mode == 0) { + struct msm_dma *dma; + struct msm_port *msm_port = UART_TO_MSM(port); + spin_lock_irqsave(&port->lock, flags); + msm_dectuart_dm_init(pdectuart); + msm_set_baud_rate(port, baud, &flags); + msm_dectuart_pipe_flush(pdectuart); + msm_stop_tx(port); + + dma = &msm_port->rx_dma; + if (dma->chan) {/* Terminate if any */ + msm_stop_dma(port, dma); + } + dma = &msm_port->tx_dma; + if (dma->chan) { + msm_stop_dma(port, dma); + } + pdectuart->open = 1; + spin_unlock_irqrestore(&port->lock, flags); + } +} +/**--------------------------------------------------------------------------------**\ +\**--------------------------------------------------------------------------------**/ +static void msm_serial_console_stop(void) { + struct _msm_dectuart *pdectuart = &msm_dectuart; + struct uart_port *port = pdectuart->port; + if(port){ + msm_dectuart_dm_save(pdectuart); + console_stop(port->cons); + } +} +/**--------------------------------------------------------------------------------**\ +\**--------------------------------------------------------------------------------**/ +static void msm_serial_console_start(void) { + unsigned long flags; + struct _msm_dectuart *pdectuart = &msm_dectuart; + struct uart_port *port = pdectuart->port; + if(port){ + struct msm_port *msm_port = UART_TO_MSM(port); + spin_lock_irqsave(&port->lock, flags); + /*--- msm_set_baud_rate(port, 115200, &flags); ---*/ + msm_dectuart_dm_restore(pdectuart); + msm_start_rx_dma(msm_port); + pdectuart->open = 0; + spin_unlock_irqrestore(&port->lock, flags); + console_start(port->cons); + } +} +/**--------------------------------------------------------------------------------**\ +\**--------------------------------------------------------------------------------**/ +static void msm_serial_dectuart_exit(void){ + struct _msm_dectuart *pdectuart = &msm_dectuart; + /*--- pr_info("%s\n", __func__); ---*/ + pdectuart->open = 0; +} +#endif/*--- #if defined(CONFIG_AVM_ENHANCED) ---*/ + module_init(msm_serial_init); module_exit(msm_serial_exit);