diff options
author | Scott Wood <scottwood@freescale.com> | 2014-04-07 23:49:35 (GMT) |
---|---|---|
committer | Scott Wood <scottwood@freescale.com> | 2014-04-07 23:49:35 (GMT) |
commit | 62b8c978ee6b8d135d9e7953221de58000dba986 (patch) | |
tree | 683b04b2e627f6710c22c151b23c8cc9a165315e /drivers/tty/serial/xilinx_uartps.c | |
parent | 78fd82238d0e5716578c326404184a27ba67fd6e (diff) | |
download | linux-fsl-qoriq-62b8c978ee6b8d135d9e7953221de58000dba986.tar.xz |
Rewind v3.13-rc3+ (78fd82238d0e5716) to v3.12
Diffstat (limited to 'drivers/tty/serial/xilinx_uartps.c')
-rw-r--r-- | drivers/tty/serial/xilinx_uartps.c | 551 |
1 files changed, 74 insertions, 477 deletions
diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index e46e9f3..7e4150a 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -1,7 +1,7 @@ /* * Xilinx PS UART driver * - * 2011 - 2013 (C) Xilinx Inc. + * 2011 (c) Xilinx Inc. * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General Public @@ -11,17 +11,13 @@ * */ -#if defined(CONFIG_SERIAL_XILINX_PS_UART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/platform_device.h> #include <linux/serial.h> -#include <linux/console.h> #include <linux/serial_core.h> #include <linux/slab.h> #include <linux/tty.h> #include <linux/tty_flip.h> +#include <linux/console.h> #include <linux/clk.h> #include <linux/irq.h> #include <linux/io.h> @@ -33,22 +29,12 @@ #define XUARTPS_MAJOR 0 /* use dynamic node allocation */ #define XUARTPS_MINOR 0 /* works best with devtmpfs */ #define XUARTPS_NR_PORTS 2 -#define XUARTPS_FIFO_SIZE 64 /* FIFO size */ +#define XUARTPS_FIFO_SIZE 16 /* FIFO size */ #define XUARTPS_REGISTER_SPACE 0xFFF #define xuartps_readl(offset) ioread32(port->membase + offset) #define xuartps_writel(val, offset) iowrite32(val, port->membase + offset) -/* Rx Trigger level */ -static int rx_trigger_level = 56; -module_param(rx_trigger_level, uint, S_IRUGO); -MODULE_PARM_DESC(rx_trigger_level, "Rx trigger level, 1-63 bytes"); - -/* Rx Timeout */ -static int rx_timeout = 10; -module_param(rx_timeout, uint, S_IRUGO); -MODULE_PARM_DESC(rx_timeout, "Rx timeout, 1-255"); - /********************************Register Map********************************/ /** UART * @@ -142,9 +128,6 @@ MODULE_PARM_DESC(rx_timeout, "Rx timeout, 1-255"); #define XUARTPS_IXR_RXEMPTY 0x00000002 /* RX FIFO empty interrupt. */ #define XUARTPS_IXR_MASK 0x00001FFF /* Valid bit mask */ -/* Goes in read_status_mask for break detection as the HW doesn't do it*/ -#define XUARTPS_IXR_BRK 0x80000000 - /** Channel Status Register * * The channel status register (CSR) is provided to enable the control logic @@ -156,27 +139,15 @@ MODULE_PARM_DESC(rx_timeout, "Rx timeout, 1-255"); #define XUARTPS_SR_TXFULL 0x00000010 /* TX FIFO full */ #define XUARTPS_SR_RXTRIG 0x00000001 /* Rx Trigger */ -/* baud dividers min/max values */ -#define XUARTPS_BDIV_MIN 4 -#define XUARTPS_BDIV_MAX 255 -#define XUARTPS_CD_MAX 65535 - /** * struct xuartps - device data - * @port Pointer to the UART port - * @refclk Reference clock - * @aperclk APB clock - * @baud Current baud rate - * @clk_rate_change_nb Notifier block for clock changes + * @refclk Reference clock + * @aperclk APB clock */ struct xuartps { - struct uart_port *port; struct clk *refclk; struct clk *aperclk; - unsigned int baud; - struct notifier_block clk_rate_change_nb; }; -#define to_xuartps(_nb) container_of(_nb, struct xuartps, clk_rate_change_nb); /** * xuartps_isr - Interrupt handler @@ -200,23 +171,6 @@ static irqreturn_t xuartps_isr(int irq, void *dev_id) */ isrstatus = xuartps_readl(XUARTPS_ISR_OFFSET); - /* - * There is no hardware break detection, so we interpret framing - * error with all-zeros data as a break sequence. Most of the time, - * there's another non-zero byte at the end of the sequence. - */ - - if (isrstatus & XUARTPS_IXR_FRAMING) { - while (!(xuartps_readl(XUARTPS_SR_OFFSET) & - XUARTPS_SR_RXEMPTY)) { - if (!xuartps_readl(XUARTPS_FIFO_OFFSET)) { - port->read_status_mask |= XUARTPS_IXR_BRK; - isrstatus &= ~XUARTPS_IXR_FRAMING; - } - } - xuartps_writel(XUARTPS_IXR_FRAMING, XUARTPS_ISR_OFFSET); - } - /* drop byte with parity error if IGNPAR specified */ if (isrstatus & port->ignore_status_mask & XUARTPS_IXR_PARITY) isrstatus &= ~(XUARTPS_IXR_RXTRIG | XUARTPS_IXR_TOUT); @@ -230,30 +184,6 @@ static irqreturn_t xuartps_isr(int irq, void *dev_id) while ((xuartps_readl(XUARTPS_SR_OFFSET) & XUARTPS_SR_RXEMPTY) != XUARTPS_SR_RXEMPTY) { data = xuartps_readl(XUARTPS_FIFO_OFFSET); - - /* Non-NULL byte after BREAK is garbage (99%) */ - if (data && (port->read_status_mask & - XUARTPS_IXR_BRK)) { - port->read_status_mask &= ~XUARTPS_IXR_BRK; - port->icount.brk++; - if (uart_handle_break(port)) - continue; - } - - /* - * uart_handle_sysrq_char() doesn't work if - * spinlocked, for some reason - */ - if (port->sysrq) { - spin_unlock(&port->lock); - if (uart_handle_sysrq_char(port, - (unsigned char)data)) { - spin_lock(&port->lock); - continue; - } - spin_lock(&port->lock); - } - port->icount.rx++; if (isrstatus & XUARTPS_IXR_PARITY) { @@ -317,196 +247,63 @@ static irqreturn_t xuartps_isr(int irq, void *dev_id) } /** - * xuartps_calc_baud_divs - Calculate baud rate divisors - * @clk: UART module input clock - * @baud: Desired baud rate - * @rbdiv: BDIV value (return value) - * @rcd: CD value (return value) - * @div8: Value for clk_sel bit in mod (return value) - * Returns baud rate, requested baud when possible, or actual baud when there - * was too much error, zero if no valid divisors are found. + * xuartps_set_baud_rate - Calculate and set the baud rate + * @port: Handle to the uart port structure + * @baud: Baud rate to set * - * Formula to obtain baud rate is - * baud_tx/rx rate = clk/CD * (BDIV + 1) - * input_clk = (Uart User Defined Clock or Apb Clock) - * depends on UCLKEN in MR Reg - * clk = input_clk or input_clk/8; - * depends on CLKS in MR reg - * CD and BDIV depends on values in - * baud rate generate register - * baud rate clock divisor register - */ -static unsigned int xuartps_calc_baud_divs(unsigned int clk, unsigned int baud, - u32 *rbdiv, u32 *rcd, int *div8) + * Returns baud rate, requested baud when possible, or actual baud when there + * was too much error + **/ +static unsigned int xuartps_set_baud_rate(struct uart_port *port, + unsigned int baud) { - u32 cd, bdiv; - unsigned int calc_baud; - unsigned int bestbaud = 0; + unsigned int sel_clk; + unsigned int calc_baud = 0; + unsigned int brgr_val, brdiv_val; unsigned int bauderror; - unsigned int besterror = ~0; - if (baud < clk / ((XUARTPS_BDIV_MAX + 1) * XUARTPS_CD_MAX)) { - *div8 = 1; - clk /= 8; - } else { - *div8 = 0; - } + /* Formula to obtain baud rate is + * baud_tx/rx rate = sel_clk/CD * (BDIV + 1) + * input_clk = (Uart User Defined Clock or Apb Clock) + * depends on UCLKEN in MR Reg + * sel_clk = input_clk or input_clk/8; + * depends on CLKS in MR reg + * CD and BDIV depends on values in + * baud rate generate register + * baud rate clock divisor register + */ + sel_clk = port->uartclk; + if (xuartps_readl(XUARTPS_MR_OFFSET) & XUARTPS_MR_CLKSEL) + sel_clk = sel_clk / 8; + + /* Find the best values for baud generation */ + for (brdiv_val = 4; brdiv_val < 255; brdiv_val++) { - for (bdiv = XUARTPS_BDIV_MIN; bdiv <= XUARTPS_BDIV_MAX; bdiv++) { - cd = DIV_ROUND_CLOSEST(clk, baud * (bdiv + 1)); - if (cd < 1 || cd > XUARTPS_CD_MAX) + brgr_val = sel_clk / (baud * (brdiv_val + 1)); + if (brgr_val < 2 || brgr_val > 65535) continue; - calc_baud = clk / (cd * (bdiv + 1)); + calc_baud = sel_clk / (brgr_val * (brdiv_val + 1)); if (baud > calc_baud) bauderror = baud - calc_baud; else bauderror = calc_baud - baud; - if (besterror > bauderror) { - *rbdiv = bdiv; - *rcd = cd; - bestbaud = calc_baud; - besterror = bauderror; + /* use the values when percent error is acceptable */ + if (((bauderror * 100) / baud) < 3) { + calc_baud = baud; + break; } } - /* use the values when percent error is acceptable */ - if (((besterror * 100) / baud) < 3) - bestbaud = baud; - - return bestbaud; -} -/** - * xuartps_set_baud_rate - Calculate and set the baud rate - * @port: Handle to the uart port structure - * @baud: Baud rate to set - * Returns baud rate, requested baud when possible, or actual baud when there - * was too much error, zero if no valid divisors are found. - */ -static unsigned int xuartps_set_baud_rate(struct uart_port *port, - unsigned int baud) -{ - unsigned int calc_baud; - u32 cd = 0, bdiv = 0; - u32 mreg; - int div8; - struct xuartps *xuartps = port->private_data; - - calc_baud = xuartps_calc_baud_divs(port->uartclk, baud, &bdiv, &cd, - &div8); - - /* Write new divisors to hardware */ - mreg = xuartps_readl(XUARTPS_MR_OFFSET); - if (div8) - mreg |= XUARTPS_MR_CLKSEL; - else - mreg &= ~XUARTPS_MR_CLKSEL; - xuartps_writel(mreg, XUARTPS_MR_OFFSET); - xuartps_writel(cd, XUARTPS_BAUDGEN_OFFSET); - xuartps_writel(bdiv, XUARTPS_BAUDDIV_OFFSET); - xuartps->baud = baud; + /* Set the values for the new baud rate */ + xuartps_writel(brgr_val, XUARTPS_BAUDGEN_OFFSET); + xuartps_writel(brdiv_val, XUARTPS_BAUDDIV_OFFSET); return calc_baud; } -#ifdef CONFIG_COMMON_CLK -/** - * xuartps_clk_notitifer_cb - Clock notifier callback - * @nb: Notifier block - * @event: Notify event - * @data: Notifier data - * Returns NOTIFY_OK on success, NOTIFY_BAD on error. - */ -static int xuartps_clk_notifier_cb(struct notifier_block *nb, - unsigned long event, void *data) -{ - u32 ctrl_reg; - struct uart_port *port; - int locked = 0; - struct clk_notifier_data *ndata = data; - unsigned long flags = 0; - struct xuartps *xuartps = to_xuartps(nb); - - port = xuartps->port; - if (port->suspended) - return NOTIFY_OK; - - switch (event) { - case PRE_RATE_CHANGE: - { - u32 bdiv; - u32 cd; - int div8; - - /* - * Find out if current baud-rate can be achieved with new clock - * frequency. - */ - if (!xuartps_calc_baud_divs(ndata->new_rate, xuartps->baud, - &bdiv, &cd, &div8)) - return NOTIFY_BAD; - - spin_lock_irqsave(&xuartps->port->lock, flags); - - /* Disable the TX and RX to set baud rate */ - xuartps_writel(xuartps_readl(XUARTPS_CR_OFFSET) | - (XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS), - XUARTPS_CR_OFFSET); - - spin_unlock_irqrestore(&xuartps->port->lock, flags); - - return NOTIFY_OK; - } - case POST_RATE_CHANGE: - /* - * Set clk dividers to generate correct baud with new clock - * frequency. - */ - - spin_lock_irqsave(&xuartps->port->lock, flags); - - locked = 1; - port->uartclk = ndata->new_rate; - - xuartps->baud = xuartps_set_baud_rate(xuartps->port, - xuartps->baud); - /* fall through */ - case ABORT_RATE_CHANGE: - if (!locked) - spin_lock_irqsave(&xuartps->port->lock, flags); - - /* Set TX/RX Reset */ - xuartps_writel(xuartps_readl(XUARTPS_CR_OFFSET) | - (XUARTPS_CR_TXRST | XUARTPS_CR_RXRST), - XUARTPS_CR_OFFSET); - - while (xuartps_readl(XUARTPS_CR_OFFSET) & - (XUARTPS_CR_TXRST | XUARTPS_CR_RXRST)) - cpu_relax(); - - /* - * Clear the RX disable and TX disable bits and then set the TX - * enable bit and RX enable bit to enable the transmitter and - * receiver. - */ - xuartps_writel(rx_timeout, XUARTPS_RXTOUT_OFFSET); - ctrl_reg = xuartps_readl(XUARTPS_CR_OFFSET); - xuartps_writel( - (ctrl_reg & ~(XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS)) | - (XUARTPS_CR_TX_EN | XUARTPS_CR_RX_EN), - XUARTPS_CR_OFFSET); - - spin_unlock_irqrestore(&xuartps->port->lock, flags); - - return NOTIFY_OK; - default: - return NOTIFY_DONE; - } -} -#endif - /*----------------------Uart Operations---------------------------*/ /** @@ -549,7 +346,7 @@ static void xuartps_start_tx(struct uart_port *port) port->state->xmit.tail = (port->state->xmit.tail + 1) & (UART_XMIT_SIZE - 1); } - xuartps_writel(XUARTPS_IXR_TXEMPTY, XUARTPS_ISR_OFFSET); + /* Enable the TX Empty interrupt */ xuartps_writel(XUARTPS_IXR_TXEMPTY, XUARTPS_IER_OFFSET); @@ -640,7 +437,7 @@ static void xuartps_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { unsigned int cval = 0; - unsigned int baud, minbaud, maxbaud; + unsigned int baud; unsigned long flags; unsigned int ctrl_reg, mode_reg; @@ -657,14 +454,8 @@ static void xuartps_set_termios(struct uart_port *port, (XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS), XUARTPS_CR_OFFSET); - /* - * Min baud rate = 6bps and Max Baud Rate is 10Mbps for 100Mhz clk - * min and max baud should be calculated here based on port->uartclk. - * this way we get a valid baud and can safely call set_baud() - */ - minbaud = port->uartclk / ((XUARTPS_BDIV_MAX + 1) * XUARTPS_CD_MAX * 8); - maxbaud = port->uartclk / (XUARTPS_BDIV_MIN + 1); - baud = uart_get_baud_rate(port, termios, old, minbaud, maxbaud); + /* Min baud rate = 6bps and Max Baud Rate is 10Mbps for 100Mhz clk */ + baud = uart_get_baud_rate(port, termios, old, 0, 10000000); baud = xuartps_set_baud_rate(port, baud); if (tty_termios_baud_rate(termios)) tty_termios_encode_baud_rate(termios, baud, baud); @@ -689,7 +480,7 @@ static void xuartps_set_termios(struct uart_port *port, | (XUARTPS_CR_TX_EN | XUARTPS_CR_RX_EN), XUARTPS_CR_OFFSET); - xuartps_writel(rx_timeout, XUARTPS_RXTOUT_OFFSET); + xuartps_writel(10, XUARTPS_RXTOUT_OFFSET); port->read_status_mask = XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_RXTRIG | XUARTPS_IXR_OVERRUN | XUARTPS_IXR_TOUT; @@ -740,17 +531,13 @@ static void xuartps_set_termios(struct uart_port *port, cval |= XUARTPS_MR_PARITY_MARK; else cval |= XUARTPS_MR_PARITY_SPACE; - } else { - if (termios->c_cflag & PARODD) + } else if (termios->c_cflag & PARODD) cval |= XUARTPS_MR_PARITY_ODD; else cval |= XUARTPS_MR_PARITY_EVEN; - } - } else { + } else cval |= XUARTPS_MR_PARITY_NONE; - } - cval |= mode_reg & 1; - xuartps_writel(cval, XUARTPS_MR_OFFSET); + xuartps_writel(cval , XUARTPS_MR_OFFSET); spin_unlock_irqrestore(&port->lock, flags); } @@ -796,17 +583,11 @@ static int xuartps_startup(struct uart_port *port) | XUARTPS_MR_PARITY_NONE | XUARTPS_MR_CHARLEN_8_BIT, XUARTPS_MR_OFFSET); - /* - * Set the RX FIFO Trigger level to use most of the FIFO, but it - * can be tuned with a module parameter - */ - xuartps_writel(rx_trigger_level, XUARTPS_RXWM_OFFSET); + /* Set the RX FIFO Trigger level to 14 assuming FIFO size as 16 */ + xuartps_writel(14, XUARTPS_RXWM_OFFSET); - /* - * Receive Timeout register is enabled but it - * can be tuned with a module parameter - */ - xuartps_writel(rx_timeout, XUARTPS_RXTOUT_OFFSET); + /* Receive Timeout register is enabled with value of 10 */ + xuartps_writel(10, XUARTPS_RXTOUT_OFFSET); /* Clear out any pending interrupts before enabling them */ xuartps_writel(xuartps_readl(XUARTPS_ISR_OFFSET), XUARTPS_ISR_OFFSET); @@ -946,54 +727,6 @@ static void xuartps_enable_ms(struct uart_port *port) /* N/A */ } -#ifdef CONFIG_CONSOLE_POLL -static int xuartps_poll_get_char(struct uart_port *port) -{ - u32 imr; - int c; - - /* Disable all interrupts */ - imr = xuartps_readl(XUARTPS_IMR_OFFSET); - xuartps_writel(imr, XUARTPS_IDR_OFFSET); - - /* Check if FIFO is empty */ - if (xuartps_readl(XUARTPS_SR_OFFSET) & XUARTPS_SR_RXEMPTY) - c = NO_POLL_CHAR; - else /* Read a character */ - c = (unsigned char) xuartps_readl(XUARTPS_FIFO_OFFSET); - - /* Enable interrupts */ - xuartps_writel(imr, XUARTPS_IER_OFFSET); - - return c; -} - -static void xuartps_poll_put_char(struct uart_port *port, unsigned char c) -{ - u32 imr; - - /* Disable all interrupts */ - imr = xuartps_readl(XUARTPS_IMR_OFFSET); - xuartps_writel(imr, XUARTPS_IDR_OFFSET); - - /* Wait until FIFO is empty */ - while (!(xuartps_readl(XUARTPS_SR_OFFSET) & XUARTPS_SR_TXEMPTY)) - cpu_relax(); - - /* Write a character */ - xuartps_writel(c, XUARTPS_FIFO_OFFSET); - - /* Wait until FIFO is empty */ - while (!(xuartps_readl(XUARTPS_SR_OFFSET) & XUARTPS_SR_TXEMPTY)) - cpu_relax(); - - /* Enable interrupts */ - xuartps_writel(imr, XUARTPS_IER_OFFSET); - - return; -} -#endif - /** The UART operations structure */ static struct uart_ops xuartps_ops = { @@ -1026,10 +759,6 @@ static struct uart_ops xuartps_ops = { .config_port = xuartps_config_port, /* Configure when driver * adds a xuartps port */ -#ifdef CONFIG_CONSOLE_POLL - .poll_get_char = xuartps_poll_get_char, - .poll_put_char = xuartps_poll_put_char, -#endif }; static struct uart_port xuartps_port[2]; @@ -1108,7 +837,7 @@ static void xuartps_console_write(struct console *co, const char *s, { struct uart_port *port = &xuartps_port[co->index]; unsigned long flags; - unsigned int imr, ctrl; + unsigned int imr; int locked = 1; if (oops_in_progress) @@ -1120,19 +849,9 @@ static void xuartps_console_write(struct console *co, const char *s, imr = xuartps_readl(XUARTPS_IMR_OFFSET); xuartps_writel(imr, XUARTPS_IDR_OFFSET); - /* - * Make sure that the tx part is enabled. Set the TX enable bit and - * clear the TX disable bit to enable the transmitter. - */ - ctrl = xuartps_readl(XUARTPS_CR_OFFSET); - xuartps_writel((ctrl & ~XUARTPS_CR_TX_DIS) | XUARTPS_CR_TX_EN, - XUARTPS_CR_OFFSET); - uart_console_write(port, s, count, xuartps_console_putchar); xuartps_console_wait_tx(port); - xuartps_writel(ctrl, XUARTPS_CR_OFFSET); - /* restore interrupt state, it seems like there may be a h/w bug * in that the interrupt enable register should not need to be * written based on the data sheet @@ -1214,119 +933,6 @@ static struct uart_driver xuartps_uart_driver = { #endif }; -#ifdef CONFIG_PM_SLEEP -/** - * xuartps_suspend - suspend event - * @device: Pointer to the device structure - * - * Returns 0 - */ -static int xuartps_suspend(struct device *device) -{ - struct uart_port *port = dev_get_drvdata(device); - struct tty_struct *tty; - struct device *tty_dev; - int may_wake = 0; - - /* Get the tty which could be NULL so don't assume it's valid */ - tty = tty_port_tty_get(&port->state->port); - if (tty) { - tty_dev = tty->dev; - may_wake = device_may_wakeup(tty_dev); - tty_kref_put(tty); - } - - /* - * Call the API provided in serial_core.c file which handles - * the suspend. - */ - uart_suspend_port(&xuartps_uart_driver, port); - if (console_suspend_enabled && !may_wake) { - struct xuartps *xuartps = port->private_data; - - clk_disable(xuartps->refclk); - clk_disable(xuartps->aperclk); - } else { - unsigned long flags = 0; - - spin_lock_irqsave(&port->lock, flags); - /* Empty the receive FIFO 1st before making changes */ - while (!(xuartps_readl(XUARTPS_SR_OFFSET) & XUARTPS_SR_RXEMPTY)) - xuartps_readl(XUARTPS_FIFO_OFFSET); - /* set RX trigger level to 1 */ - xuartps_writel(1, XUARTPS_RXWM_OFFSET); - /* disable RX timeout interrups */ - xuartps_writel(XUARTPS_IXR_TOUT, XUARTPS_IDR_OFFSET); - spin_unlock_irqrestore(&port->lock, flags); - } - - return 0; -} - -/** - * xuartps_resume - Resume after a previous suspend - * @device: Pointer to the device structure - * - * Returns 0 - */ -static int xuartps_resume(struct device *device) -{ - struct uart_port *port = dev_get_drvdata(device); - unsigned long flags = 0; - u32 ctrl_reg; - struct tty_struct *tty; - struct device *tty_dev; - int may_wake = 0; - - /* Get the tty which could be NULL so don't assume it's valid */ - tty = tty_port_tty_get(&port->state->port); - if (tty) { - tty_dev = tty->dev; - may_wake = device_may_wakeup(tty_dev); - tty_kref_put(tty); - } - - if (console_suspend_enabled && !may_wake) { - struct xuartps *xuartps = port->private_data; - - clk_enable(xuartps->aperclk); - clk_enable(xuartps->refclk); - - spin_lock_irqsave(&port->lock, flags); - - /* Set TX/RX Reset */ - xuartps_writel(xuartps_readl(XUARTPS_CR_OFFSET) | - (XUARTPS_CR_TXRST | XUARTPS_CR_RXRST), - XUARTPS_CR_OFFSET); - while (xuartps_readl(XUARTPS_CR_OFFSET) & - (XUARTPS_CR_TXRST | XUARTPS_CR_RXRST)) - cpu_relax(); - - /* restore rx timeout value */ - xuartps_writel(rx_timeout, XUARTPS_RXTOUT_OFFSET); - /* Enable Tx/Rx */ - ctrl_reg = xuartps_readl(XUARTPS_CR_OFFSET); - xuartps_writel( - (ctrl_reg & ~(XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS)) | - (XUARTPS_CR_TX_EN | XUARTPS_CR_RX_EN), - XUARTPS_CR_OFFSET); - - spin_unlock_irqrestore(&port->lock, flags); - } else { - spin_lock_irqsave(&port->lock, flags); - /* restore original rx trigger level */ - xuartps_writel(rx_trigger_level, XUARTPS_RXWM_OFFSET); - /* enable RX timeout interrupt */ - xuartps_writel(XUARTPS_IXR_TOUT, XUARTPS_IER_OFFSET); - spin_unlock_irqrestore(&port->lock, flags); - } - - return uart_resume_port(&xuartps_uart_driver, port); -} -#endif /* ! CONFIG_PM_SLEEP */ - -static SIMPLE_DEV_PM_OPS(xuartps_dev_pm_ops, xuartps_suspend, xuartps_resume); - /* --------------------------------------------------------------------- * Platform bus binding */ @@ -1343,26 +949,27 @@ static int xuartps_probe(struct platform_device *pdev) struct resource *res, *res2; struct xuartps *xuartps_data; - xuartps_data = devm_kzalloc(&pdev->dev, sizeof(*xuartps_data), - GFP_KERNEL); + xuartps_data = kzalloc(sizeof(*xuartps_data), GFP_KERNEL); if (!xuartps_data) return -ENOMEM; - xuartps_data->aperclk = devm_clk_get(&pdev->dev, "aper_clk"); + xuartps_data->aperclk = clk_get(&pdev->dev, "aper_clk"); if (IS_ERR(xuartps_data->aperclk)) { dev_err(&pdev->dev, "aper_clk clock not found.\n"); - return PTR_ERR(xuartps_data->aperclk); + rc = PTR_ERR(xuartps_data->aperclk); + goto err_out_free; } - xuartps_data->refclk = devm_clk_get(&pdev->dev, "ref_clk"); + xuartps_data->refclk = clk_get(&pdev->dev, "ref_clk"); if (IS_ERR(xuartps_data->refclk)) { dev_err(&pdev->dev, "ref_clk clock not found.\n"); - return PTR_ERR(xuartps_data->refclk); + rc = PTR_ERR(xuartps_data->refclk); + goto err_out_clk_put_aper; } rc = clk_prepare_enable(xuartps_data->aperclk); if (rc) { dev_err(&pdev->dev, "Unable to enable APER clock.\n"); - return rc; + goto err_out_clk_put; } rc = clk_prepare_enable(xuartps_data->refclk); if (rc) { @@ -1382,21 +989,13 @@ static int xuartps_probe(struct platform_device *pdev) goto err_out_clk_disable; } -#ifdef CONFIG_COMMON_CLK - xuartps_data->clk_rate_change_nb.notifier_call = - xuartps_clk_notifier_cb; - if (clk_notifier_register(xuartps_data->refclk, - &xuartps_data->clk_rate_change_nb)) - dev_warn(&pdev->dev, "Unable to register clock notifier.\n"); -#endif - /* Initialize the port structure */ port = xuartps_get_port(); if (!port) { dev_err(&pdev->dev, "Cannot get uart_port structure\n"); rc = -ENODEV; - goto err_out_notif_unreg; + goto err_out_clk_disable; } else { /* Register the port. * This function also registers this device with the tty layer @@ -1407,26 +1006,26 @@ static int xuartps_probe(struct platform_device *pdev) port->dev = &pdev->dev; port->uartclk = clk_get_rate(xuartps_data->refclk); port->private_data = xuartps_data; - xuartps_data->port = port; platform_set_drvdata(pdev, port); rc = uart_add_one_port(&xuartps_uart_driver, port); if (rc) { dev_err(&pdev->dev, "uart_add_one_port() failed; err=%i\n", rc); - goto err_out_notif_unreg; + goto err_out_clk_disable; } return 0; } -err_out_notif_unreg: -#ifdef CONFIG_COMMON_CLK - clk_notifier_unregister(xuartps_data->refclk, - &xuartps_data->clk_rate_change_nb); -#endif err_out_clk_disable: clk_disable_unprepare(xuartps_data->refclk); err_out_clk_dis_aper: clk_disable_unprepare(xuartps_data->aperclk); +err_out_clk_put: + clk_put(xuartps_data->refclk); +err_out_clk_put_aper: + clk_put(xuartps_data->aperclk); +err_out_free: + kfree(xuartps_data); return rc; } @@ -1444,14 +1043,13 @@ static int xuartps_remove(struct platform_device *pdev) int rc; /* Remove the xuartps port from the serial core */ -#ifdef CONFIG_COMMON_CLK - clk_notifier_unregister(xuartps_data->refclk, - &xuartps_data->clk_rate_change_nb); -#endif rc = uart_remove_one_port(&xuartps_uart_driver, port); port->mapbase = 0; clk_disable_unprepare(xuartps_data->refclk); clk_disable_unprepare(xuartps_data->aperclk); + clk_put(xuartps_data->refclk); + clk_put(xuartps_data->aperclk); + kfree(xuartps_data); return rc; } @@ -1469,7 +1067,6 @@ static struct platform_driver xuartps_platform_driver = { .owner = THIS_MODULE, .name = XUARTPS_NAME, /* Driver name */ .of_match_table = xuartps_of_match, - .pm = &xuartps_dev_pm_ops, }, }; |