/* * Print a string to the serial port trying not to disturb * any possible real use of the port... * * The console_lock must be held when we get here. * * Note that this is called with interrupts already disabled */ static void clps711xuart_console_write(struct console *co, const char *s, unsigned int count) { struct uart_port *port = clps711x_ports + co->index; unsigned int status, syscon; /* * Ensure that the port is enabled. */ syscon = clps_readl(SYSCON(port)); clps_writel(syscon | SYSCON_UARTEN, SYSCON(port)); uart_console_write(port, s, count, clps711xuart_console_putchar); /* * Finally, wait for transmitter to become empty * and restore the uart state. */ do { status = clps_readl(SYSFLG(port)); } while (status & SYSFLG_UBUSY); clps_writel(syscon, SYSCON(port)); }
static int clps711xuart_startup(struct uart_port *port) { unsigned int syscon; int retval; tx_enabled(port) = 1; /* * Allocate the IRQs */ retval = request_irq(TX_IRQ(port), clps711xuart_int_tx, 0, "clps711xuart_tx", port); if (retval) return retval; retval = request_irq(RX_IRQ(port), clps711xuart_int_rx, 0, "clps711xuart_rx", port); if (retval) { free_irq(TX_IRQ(port), port); return retval; } /* * enable the port */ syscon = clps_readl(SYSCON(port)); syscon |= SYSCON_UARTEN; clps_writel(syscon, SYSCON(port)); return 0; }
static int uart_clps711x_startup(struct uart_port *port) { struct clps711x_port *s = dev_get_drvdata(port->dev); int ret; s->tx_enabled[port->line] = 1; /* Allocate the IRQs */ ret = devm_request_irq(port->dev, TX_IRQ(port), uart_clps711x_int_tx, 0, UART_CLPS711X_NAME " TX", port); if (ret) return ret; ret = devm_request_irq(port->dev, RX_IRQ(port), uart_clps711x_int_rx, 0, UART_CLPS711X_NAME " RX", port); if (ret) { devm_free_irq(port->dev, TX_IRQ(port), port); return ret; } /* Disable break */ clps_writel(clps_readl(UBRLCR(port)) & ~UBRLCR_BREAK, UBRLCR(port)); /* Enable the port */ clps_writel(clps_readl(SYSCON(port)) | SYSCON_UARTEN, SYSCON(port)); return 0; }
static int clps711xuart_startup(struct uart_port *port, struct uart_info *info) { u_int syscon; int retval; /* * Allocate the IRQs */ retval = request_irq(TX_IRQ(port), clps711xuart_int_tx, 0, "clps711xuart_tx", info); if (retval) return retval; retval = request_irq(RX_IRQ(port), clps711xuart_int_rx, 0, "clps711xuart_rx", info); if (retval) { free_irq(TX_IRQ(port), info); return retval; } port->ops->set_mctrl(port, info->mctrl); /* * enable the port */ syscon = clps_readl(SYSCON(port)); syscon |= SYSCON_UARTEN; clps_writel(syscon, SYSCON(port)); return 0; }
static void uart_clps711x_shutdown(struct uart_port *port) { /* Free the interrupts */ devm_free_irq(port->dev, TX_IRQ(port), port); devm_free_irq(port->dev, RX_IRQ(port), port); /* Disable the port */ clps_writel(clps_readl(SYSCON(port)) & ~SYSCON_UARTEN, SYSCON(port)); }
static void __init clps711xuart_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits) { if (clps_readl(SYSCON(port)) & SYSCON_UARTEN) { unsigned int ubrlcr, quot; ubrlcr = clps_readl(UBRLCR(port)); *parity = 'n'; if (ubrlcr & UBRLCR_PRTEN) { if (ubrlcr & UBRLCR_EVENPRT) *parity = 'e'; else *parity = 'o'; } if ((ubrlcr & UBRLCR_WRDLEN_MASK) == UBRLCR_WRDLEN7) *bits = 7; else *bits = 8; quot = ubrlcr & UBRLCR_BAUD_MASK; *baud = port->uartclk / (16 * (quot + 1)); } }
static void clps711x_init_port(struct console_device *cdev) { struct clps711x_uart *s = cdev->dev->priv; u32 tmp; /* Disable the UART */ writel(readl(SYSCON(s)) & ~SYSCON_UARTEN, SYSCON(s)); /* Setup Line Control Register */ tmp = readl(s->UBRLCR) & UBRLCR_BAUD_MASK; tmp |= UBRLCR_FIFOEN | UBRLCR_WRDLEN8; /* FIFO on, 8N1 mode */ writel(tmp, s->UBRLCR); /* Set default baudrate on initialization */ clps711x_setbaudrate(cdev, CONFIG_BAUDRATE); /* Enable the UART */ writel(readl(SYSCON(s)) | SYSCON_UARTEN, SYSCON(s)); }
static void uart_clps711x_console_write(struct console *co, const char *c, unsigned n) { struct clps711x_port *s = (struct clps711x_port *)co->data; struct uart_port *port = &s->port[co->index]; u32 syscon; /* Ensure that the port is enabled */ syscon = clps_readl(SYSCON(port)); clps_writel(syscon | SYSCON_UARTEN, SYSCON(port)); uart_console_write(port, c, n, uart_clps711x_console_putchar); /* Wait for transmitter to become empty */ while (clps_readl(SYSFLG(port)) & SYSFLG_UBUSY) barrier(); /* Restore the uart state */ clps_writel(syscon, SYSCON(port)); }
/* * Print a string to the serial port trying not to disturb * any possible real use of the port... * * The console_lock must be held when we get here. * * Note that this is called with interrupts already disabled */ static void clps711xuart_console_write(struct console *co, const char *s, unsigned int count) { struct uart_port *port = clps711x_ports + co->index; unsigned int status, syscon; int i; /* * Ensure that the port is enabled. */ syscon = clps_readl(SYSCON(port)); clps_writel(syscon | SYSCON_UARTEN, SYSCON(port)); /* * Now, do each character */ for (i = 0; i < count; i++) { do { status = clps_readl(SYSFLG(port)); } while (status & SYSFLG_UTXFF); clps_writel(s[i], UARTDR(port)); if (s[i] == '\n') { do { status = clps_readl(SYSFLG(port)); } while (status & SYSFLG_UTXFF); clps_writel('\r', UARTDR(port)); } } /* * Finally, wait for transmitter to become empty * and restore the uart state. */ do { status = clps_readl(SYSFLG(port)); } while (status & SYSFLG_UBUSY); clps_writel(syscon, SYSCON(port)); }
static void clps711xuart_shutdown(struct uart_port *port) { unsigned int ubrlcr, syscon; /* * Free the interrupt */ free_irq(TX_IRQ(port), port); /* TX interrupt */ free_irq(RX_IRQ(port), port); /* RX interrupt */ /* * disable the port */ syscon = clps_readl(SYSCON(port)); syscon &= ~SYSCON_UARTEN; clps_writel(syscon, SYSCON(port)); /* * disable break condition and fifos */ ubrlcr = clps_readl(UBRLCR(port)); ubrlcr &= ~(UBRLCR_FIFOEN | UBRLCR_BREAK); clps_writel(ubrlcr, UBRLCR(port)); }
static int uart_clps711x_probe(struct platform_device *pdev) { struct clps711x_port *s; int ret, i; s = devm_kzalloc(&pdev->dev, sizeof(struct clps711x_port), GFP_KERNEL); if (!s) { dev_err(&pdev->dev, "Error allocating port structure\n"); return -ENOMEM; } platform_set_drvdata(pdev, s); s->uart_clk = devm_clk_get(&pdev->dev, "uart"); if (IS_ERR(s->uart_clk)) { dev_err(&pdev->dev, "Can't get UART clocks\n"); ret = PTR_ERR(s->uart_clk); goto err_out; } s->uart.owner = THIS_MODULE; s->uart.dev_name = "ttyCL"; s->uart.major = UART_CLPS711X_MAJOR; s->uart.minor = UART_CLPS711X_MINOR; s->uart.nr = UART_CLPS711X_NR; #ifdef CONFIG_SERIAL_CLPS711X_CONSOLE s->uart.cons = &s->console; s->uart.cons->device = uart_console_device; s->uart.cons->write = uart_clps711x_console_write; s->uart.cons->setup = uart_clps711x_console_setup; s->uart.cons->flags = CON_PRINTBUFFER; s->uart.cons->index = -1; s->uart.cons->data = s; strcpy(s->uart.cons->name, "ttyCL"); #endif ret = uart_register_driver(&s->uart); if (ret) { dev_err(&pdev->dev, "Registering UART driver failed\n"); devm_clk_put(&pdev->dev, s->uart_clk); goto err_out; } for (i = 0; i < UART_CLPS711X_NR; i++) { s->port[i].line = i; s->port[i].dev = &pdev->dev; s->port[i].irq = TX_IRQ(&s->port[i]); s->port[i].iobase = SYSCON(&s->port[i]); s->port[i].type = PORT_CLPS711X; s->port[i].fifosize = 16; s->port[i].flags = UPF_SKIP_TEST | UPF_FIXED_TYPE; s->port[i].uartclk = clk_get_rate(s->uart_clk); s->port[i].ops = &uart_clps711x_ops; WARN_ON(uart_add_one_port(&s->uart, &s->port[i])); } return 0; err_out: platform_set_drvdata(pdev, NULL); return ret; }