|
@@ -67,7 +67,6 @@
|
|
#include <linux/serial.h>
|
|
#include <linux/serial.h>
|
|
#include <linux/sysrq.h>
|
|
#include <linux/sysrq.h>
|
|
#include <linux/console.h>
|
|
#include <linux/console.h>
|
|
-
|
|
|
|
#include <linux/delay.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/io.h>
|
|
#include <linux/io.h>
|
|
|
|
|
|
@@ -111,8 +110,8 @@ static struct device_node *mpc52xx_uart_nodes[MPC52xx_PSC_MAXNUM];
|
|
static void mpc52xx_uart_of_enumerate(void);
|
|
static void mpc52xx_uart_of_enumerate(void);
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
+
|
|
#define PSC(port) ((struct mpc52xx_psc __iomem *)((port)->membase))
|
|
#define PSC(port) ((struct mpc52xx_psc __iomem *)((port)->membase))
|
|
-#define FIFO(port) ((struct mpc52xx_psc_fifo __iomem *)(PSC(port)+1))
|
|
|
|
|
|
|
|
|
|
|
|
/* Forward declaration of the interruption handling routine */
|
|
/* Forward declaration of the interruption handling routine */
|
|
@@ -137,6 +136,162 @@ static struct of_device_id mpc52xx_uart_of_match[] = {
|
|
};
|
|
};
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
+/* ======================================================================== */
|
|
|
|
+/* PSC fifo operations for isolating differences between 52xx and 512x */
|
|
|
|
+/* ======================================================================== */
|
|
|
|
+
|
|
|
|
+struct psc_ops {
|
|
|
|
+ void (*fifo_init)(struct uart_port *port);
|
|
|
|
+ int (*raw_rx_rdy)(struct uart_port *port);
|
|
|
|
+ int (*raw_tx_rdy)(struct uart_port *port);
|
|
|
|
+ int (*rx_rdy)(struct uart_port *port);
|
|
|
|
+ int (*tx_rdy)(struct uart_port *port);
|
|
|
|
+ int (*tx_empty)(struct uart_port *port);
|
|
|
|
+ void (*stop_rx)(struct uart_port *port);
|
|
|
|
+ void (*start_tx)(struct uart_port *port);
|
|
|
|
+ void (*stop_tx)(struct uart_port *port);
|
|
|
|
+ void (*rx_clr_irq)(struct uart_port *port);
|
|
|
|
+ void (*tx_clr_irq)(struct uart_port *port);
|
|
|
|
+ void (*write_char)(struct uart_port *port, unsigned char c);
|
|
|
|
+ unsigned char (*read_char)(struct uart_port *port);
|
|
|
|
+ void (*cw_disable_ints)(struct uart_port *port);
|
|
|
|
+ void (*cw_restore_ints)(struct uart_port *port);
|
|
|
|
+ unsigned long (*getuartclk)(void *p);
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+#define FIFO_52xx(port) ((struct mpc52xx_psc_fifo __iomem *)(PSC(port)+1))
|
|
|
|
+static void mpc52xx_psc_fifo_init(struct uart_port *port)
|
|
|
|
+{
|
|
|
|
+ struct mpc52xx_psc __iomem *psc = PSC(port);
|
|
|
|
+ struct mpc52xx_psc_fifo __iomem *fifo = FIFO_52xx(port);
|
|
|
|
+
|
|
|
|
+ /* /32 prescaler */
|
|
|
|
+ out_be16(&psc->mpc52xx_psc_clock_select, 0xdd00);
|
|
|
|
+
|
|
|
|
+ out_8(&fifo->rfcntl, 0x00);
|
|
|
|
+ out_be16(&fifo->rfalarm, 0x1ff);
|
|
|
|
+ out_8(&fifo->tfcntl, 0x07);
|
|
|
|
+ out_be16(&fifo->tfalarm, 0x80);
|
|
|
|
+
|
|
|
|
+ port->read_status_mask |= MPC52xx_PSC_IMR_RXRDY | MPC52xx_PSC_IMR_TXRDY;
|
|
|
|
+ out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int mpc52xx_psc_raw_rx_rdy(struct uart_port *port)
|
|
|
|
+{
|
|
|
|
+ return in_be16(&PSC(port)->mpc52xx_psc_status)
|
|
|
|
+ & MPC52xx_PSC_SR_RXRDY;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int mpc52xx_psc_raw_tx_rdy(struct uart_port *port)
|
|
|
|
+{
|
|
|
|
+ return in_be16(&PSC(port)->mpc52xx_psc_status)
|
|
|
|
+ & MPC52xx_PSC_SR_TXRDY;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+static int mpc52xx_psc_rx_rdy(struct uart_port *port)
|
|
|
|
+{
|
|
|
|
+ return in_be16(&PSC(port)->mpc52xx_psc_isr)
|
|
|
|
+ & port->read_status_mask
|
|
|
|
+ & MPC52xx_PSC_IMR_RXRDY;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int mpc52xx_psc_tx_rdy(struct uart_port *port)
|
|
|
|
+{
|
|
|
|
+ return in_be16(&PSC(port)->mpc52xx_psc_isr)
|
|
|
|
+ & port->read_status_mask
|
|
|
|
+ & MPC52xx_PSC_IMR_TXRDY;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int mpc52xx_psc_tx_empty(struct uart_port *port)
|
|
|
|
+{
|
|
|
|
+ return in_be16(&PSC(port)->mpc52xx_psc_status)
|
|
|
|
+ & MPC52xx_PSC_SR_TXEMP;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void mpc52xx_psc_start_tx(struct uart_port *port)
|
|
|
|
+{
|
|
|
|
+ port->read_status_mask |= MPC52xx_PSC_IMR_TXRDY;
|
|
|
|
+ out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void mpc52xx_psc_stop_tx(struct uart_port *port)
|
|
|
|
+{
|
|
|
|
+ port->read_status_mask &= ~MPC52xx_PSC_IMR_TXRDY;
|
|
|
|
+ out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void mpc52xx_psc_stop_rx(struct uart_port *port)
|
|
|
|
+{
|
|
|
|
+ port->read_status_mask &= ~MPC52xx_PSC_IMR_RXRDY;
|
|
|
|
+ out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void mpc52xx_psc_rx_clr_irq(struct uart_port *port)
|
|
|
|
+{
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void mpc52xx_psc_tx_clr_irq(struct uart_port *port)
|
|
|
|
+{
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void mpc52xx_psc_write_char(struct uart_port *port, unsigned char c)
|
|
|
|
+{
|
|
|
|
+ out_8(&PSC(port)->mpc52xx_psc_buffer_8, c);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static unsigned char mpc52xx_psc_read_char(struct uart_port *port)
|
|
|
|
+{
|
|
|
|
+ return in_8(&PSC(port)->mpc52xx_psc_buffer_8);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void mpc52xx_psc_cw_disable_ints(struct uart_port *port)
|
|
|
|
+{
|
|
|
|
+ out_be16(&PSC(port)->mpc52xx_psc_imr, 0);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void mpc52xx_psc_cw_restore_ints(struct uart_port *port)
|
|
|
|
+{
|
|
|
|
+ out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* Search for bus-frequency property in this node or a parent */
|
|
|
|
+static unsigned long mpc52xx_getuartclk(void *p)
|
|
|
|
+{
|
|
|
|
+#if defined(CONFIG_PPC_MERGE)
|
|
|
|
+ /*
|
|
|
|
+ * 5200 UARTs have a / 32 prescaler
|
|
|
|
+ * but the generic serial code assumes 16
|
|
|
|
+ * so return ipb freq / 2
|
|
|
|
+ */
|
|
|
|
+ return mpc52xx_find_ipb_freq(p) / 2;
|
|
|
|
+#else
|
|
|
|
+ pr_debug("unexpected call to mpc52xx_getuartclk with arch/ppc\n");
|
|
|
|
+ return NULL;
|
|
|
|
+#endif
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static struct psc_ops mpc52xx_psc_ops = {
|
|
|
|
+ .fifo_init = mpc52xx_psc_fifo_init,
|
|
|
|
+ .raw_rx_rdy = mpc52xx_psc_raw_rx_rdy,
|
|
|
|
+ .raw_tx_rdy = mpc52xx_psc_raw_tx_rdy,
|
|
|
|
+ .rx_rdy = mpc52xx_psc_rx_rdy,
|
|
|
|
+ .tx_rdy = mpc52xx_psc_tx_rdy,
|
|
|
|
+ .tx_empty = mpc52xx_psc_tx_empty,
|
|
|
|
+ .stop_rx = mpc52xx_psc_stop_rx,
|
|
|
|
+ .start_tx = mpc52xx_psc_start_tx,
|
|
|
|
+ .stop_tx = mpc52xx_psc_stop_tx,
|
|
|
|
+ .rx_clr_irq = mpc52xx_psc_rx_clr_irq,
|
|
|
|
+ .tx_clr_irq = mpc52xx_psc_tx_clr_irq,
|
|
|
|
+ .write_char = mpc52xx_psc_write_char,
|
|
|
|
+ .read_char = mpc52xx_psc_read_char,
|
|
|
|
+ .cw_disable_ints = mpc52xx_psc_cw_disable_ints,
|
|
|
|
+ .cw_restore_ints = mpc52xx_psc_cw_restore_ints,
|
|
|
|
+ .getuartclk = mpc52xx_getuartclk,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static struct psc_ops *psc_ops = &mpc52xx_psc_ops;
|
|
|
|
|
|
/* ======================================================================== */
|
|
/* ======================================================================== */
|
|
/* UART operations */
|
|
/* UART operations */
|
|
@@ -145,8 +300,7 @@ static struct of_device_id mpc52xx_uart_of_match[] = {
|
|
static unsigned int
|
|
static unsigned int
|
|
mpc52xx_uart_tx_empty(struct uart_port *port)
|
|
mpc52xx_uart_tx_empty(struct uart_port *port)
|
|
{
|
|
{
|
|
- int status = in_be16(&PSC(port)->mpc52xx_psc_status);
|
|
|
|
- return (status & MPC52xx_PSC_SR_TXEMP) ? TIOCSER_TEMT : 0;
|
|
|
|
|
|
+ return psc_ops->tx_empty(port) ? TIOCSER_TEMT : 0;
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
static void
|
|
@@ -166,16 +320,14 @@ static void
|
|
mpc52xx_uart_stop_tx(struct uart_port *port)
|
|
mpc52xx_uart_stop_tx(struct uart_port *port)
|
|
{
|
|
{
|
|
/* port->lock taken by caller */
|
|
/* port->lock taken by caller */
|
|
- port->read_status_mask &= ~MPC52xx_PSC_IMR_TXRDY;
|
|
|
|
- out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask);
|
|
|
|
|
|
+ psc_ops->stop_tx(port);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
static void
|
|
mpc52xx_uart_start_tx(struct uart_port *port)
|
|
mpc52xx_uart_start_tx(struct uart_port *port)
|
|
{
|
|
{
|
|
/* port->lock taken by caller */
|
|
/* port->lock taken by caller */
|
|
- port->read_status_mask |= MPC52xx_PSC_IMR_TXRDY;
|
|
|
|
- out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask);
|
|
|
|
|
|
+ psc_ops->start_tx(port);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
static void
|
|
@@ -188,8 +340,7 @@ mpc52xx_uart_send_xchar(struct uart_port *port, char ch)
|
|
if (ch) {
|
|
if (ch) {
|
|
/* Make sure tx interrupts are on */
|
|
/* Make sure tx interrupts are on */
|
|
/* Truly necessary ??? They should be anyway */
|
|
/* Truly necessary ??? They should be anyway */
|
|
- port->read_status_mask |= MPC52xx_PSC_IMR_TXRDY;
|
|
|
|
- out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask);
|
|
|
|
|
|
+ psc_ops->start_tx(port);
|
|
}
|
|
}
|
|
|
|
|
|
spin_unlock_irqrestore(&port->lock, flags);
|
|
spin_unlock_irqrestore(&port->lock, flags);
|
|
@@ -199,8 +350,7 @@ static void
|
|
mpc52xx_uart_stop_rx(struct uart_port *port)
|
|
mpc52xx_uart_stop_rx(struct uart_port *port)
|
|
{
|
|
{
|
|
/* port->lock taken by caller */
|
|
/* port->lock taken by caller */
|
|
- port->read_status_mask &= ~MPC52xx_PSC_IMR_RXRDY;
|
|
|
|
- out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask);
|
|
|
|
|
|
+ psc_ops->stop_rx(port);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
static void
|
|
@@ -227,7 +377,6 @@ static int
|
|
mpc52xx_uart_startup(struct uart_port *port)
|
|
mpc52xx_uart_startup(struct uart_port *port)
|
|
{
|
|
{
|
|
struct mpc52xx_psc __iomem *psc = PSC(port);
|
|
struct mpc52xx_psc __iomem *psc = PSC(port);
|
|
- struct mpc52xx_psc_fifo __iomem *fifo = FIFO(port);
|
|
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
/* Request IRQ */
|
|
/* Request IRQ */
|
|
@@ -242,15 +391,7 @@ mpc52xx_uart_startup(struct uart_port *port)
|
|
|
|
|
|
out_be32(&psc->sicr, 0); /* UART mode DCD ignored */
|
|
out_be32(&psc->sicr, 0); /* UART mode DCD ignored */
|
|
|
|
|
|
- out_be16(&psc->mpc52xx_psc_clock_select, 0xdd00); /* /16 prescaler on */
|
|
|
|
-
|
|
|
|
- out_8(&fifo->rfcntl, 0x00);
|
|
|
|
- out_be16(&fifo->rfalarm, 0x1ff);
|
|
|
|
- out_8(&fifo->tfcntl, 0x07);
|
|
|
|
- out_be16(&fifo->tfalarm, 0x80);
|
|
|
|
-
|
|
|
|
- port->read_status_mask |= MPC52xx_PSC_IMR_RXRDY | MPC52xx_PSC_IMR_TXRDY;
|
|
|
|
- out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask);
|
|
|
|
|
|
+ psc_ops->fifo_init(port);
|
|
|
|
|
|
out_8(&psc->command, MPC52xx_PSC_TX_ENABLE);
|
|
out_8(&psc->command, MPC52xx_PSC_TX_ENABLE);
|
|
out_8(&psc->command, MPC52xx_PSC_RX_ENABLE);
|
|
out_8(&psc->command, MPC52xx_PSC_RX_ENABLE);
|
|
@@ -333,8 +474,7 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new,
|
|
* boot for the console, all stuff is not yet ready to receive at that
|
|
* boot for the console, all stuff is not yet ready to receive at that
|
|
* time and that just makes the kernel oops */
|
|
* time and that just makes the kernel oops */
|
|
/* while (j-- && mpc52xx_uart_int_rx_chars(port)); */
|
|
/* while (j-- && mpc52xx_uart_int_rx_chars(port)); */
|
|
- while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP) &&
|
|
|
|
- --j)
|
|
|
|
|
|
+ while (!mpc52xx_uart_tx_empty(port) && --j)
|
|
udelay(1);
|
|
udelay(1);
|
|
|
|
|
|
if (!j)
|
|
if (!j)
|
|
@@ -462,11 +602,9 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port)
|
|
unsigned short status;
|
|
unsigned short status;
|
|
|
|
|
|
/* While we can read, do so ! */
|
|
/* While we can read, do so ! */
|
|
- while ((status = in_be16(&PSC(port)->mpc52xx_psc_status)) &
|
|
|
|
- MPC52xx_PSC_SR_RXRDY) {
|
|
|
|
-
|
|
|
|
|
|
+ while (psc_ops->raw_rx_rdy(port)) {
|
|
/* Get the char */
|
|
/* Get the char */
|
|
- ch = in_8(&PSC(port)->mpc52xx_psc_buffer_8);
|
|
|
|
|
|
+ ch = psc_ops->read_char(port);
|
|
|
|
|
|
/* Handle sysreq char */
|
|
/* Handle sysreq char */
|
|
#ifdef SUPPORT_SYSRQ
|
|
#ifdef SUPPORT_SYSRQ
|
|
@@ -481,6 +619,8 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port)
|
|
flag = TTY_NORMAL;
|
|
flag = TTY_NORMAL;
|
|
port->icount.rx++;
|
|
port->icount.rx++;
|
|
|
|
|
|
|
|
+ status = in_be16(&PSC(port)->mpc52xx_psc_status);
|
|
|
|
+
|
|
if (status & (MPC52xx_PSC_SR_PE |
|
|
if (status & (MPC52xx_PSC_SR_PE |
|
|
MPC52xx_PSC_SR_FE |
|
|
MPC52xx_PSC_SR_FE |
|
|
MPC52xx_PSC_SR_RB)) {
|
|
MPC52xx_PSC_SR_RB)) {
|
|
@@ -510,7 +650,7 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port)
|
|
|
|
|
|
tty_flip_buffer_push(tty);
|
|
tty_flip_buffer_push(tty);
|
|
|
|
|
|
- return in_be16(&PSC(port)->mpc52xx_psc_status) & MPC52xx_PSC_SR_RXRDY;
|
|
|
|
|
|
+ return psc_ops->raw_rx_rdy(port);
|
|
}
|
|
}
|
|
|
|
|
|
static inline int
|
|
static inline int
|
|
@@ -520,7 +660,7 @@ mpc52xx_uart_int_tx_chars(struct uart_port *port)
|
|
|
|
|
|
/* Process out of band chars */
|
|
/* Process out of band chars */
|
|
if (port->x_char) {
|
|
if (port->x_char) {
|
|
- out_8(&PSC(port)->mpc52xx_psc_buffer_8, port->x_char);
|
|
|
|
|
|
+ psc_ops->write_char(port, port->x_char);
|
|
port->icount.tx++;
|
|
port->icount.tx++;
|
|
port->x_char = 0;
|
|
port->x_char = 0;
|
|
return 1;
|
|
return 1;
|
|
@@ -533,8 +673,8 @@ mpc52xx_uart_int_tx_chars(struct uart_port *port)
|
|
}
|
|
}
|
|
|
|
|
|
/* Send chars */
|
|
/* Send chars */
|
|
- while (in_be16(&PSC(port)->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXRDY) {
|
|
|
|
- out_8(&PSC(port)->mpc52xx_psc_buffer_8, xmit->buf[xmit->tail]);
|
|
|
|
|
|
+ while (psc_ops->raw_tx_rdy(port)) {
|
|
|
|
+ psc_ops->write_char(port, xmit->buf[xmit->tail]);
|
|
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
|
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
|
port->icount.tx++;
|
|
port->icount.tx++;
|
|
if (uart_circ_empty(xmit))
|
|
if (uart_circ_empty(xmit))
|
|
@@ -560,7 +700,6 @@ mpc52xx_uart_int(int irq, void *dev_id)
|
|
struct uart_port *port = dev_id;
|
|
struct uart_port *port = dev_id;
|
|
unsigned long pass = ISR_PASS_LIMIT;
|
|
unsigned long pass = ISR_PASS_LIMIT;
|
|
unsigned int keepgoing;
|
|
unsigned int keepgoing;
|
|
- unsigned short status;
|
|
|
|
|
|
|
|
spin_lock(&port->lock);
|
|
spin_lock(&port->lock);
|
|
|
|
|
|
@@ -569,18 +708,12 @@ mpc52xx_uart_int(int irq, void *dev_id)
|
|
/* If we don't find anything to do, we stop */
|
|
/* If we don't find anything to do, we stop */
|
|
keepgoing = 0;
|
|
keepgoing = 0;
|
|
|
|
|
|
- /* Read status */
|
|
|
|
- status = in_be16(&PSC(port)->mpc52xx_psc_isr);
|
|
|
|
- status &= port->read_status_mask;
|
|
|
|
-
|
|
|
|
- /* Do we need to receive chars ? */
|
|
|
|
- /* For this RX interrupts must be on and some chars waiting */
|
|
|
|
- if (status & MPC52xx_PSC_IMR_RXRDY)
|
|
|
|
|
|
+ psc_ops->rx_clr_irq(port);
|
|
|
|
+ if (psc_ops->rx_rdy(port))
|
|
keepgoing |= mpc52xx_uart_int_rx_chars(port);
|
|
keepgoing |= mpc52xx_uart_int_rx_chars(port);
|
|
|
|
|
|
- /* Do we need to send chars ? */
|
|
|
|
- /* For this, TX must be ready and TX interrupt enabled */
|
|
|
|
- if (status & MPC52xx_PSC_IMR_TXRDY)
|
|
|
|
|
|
+ psc_ops->tx_clr_irq(port);
|
|
|
|
+ if (psc_ops->tx_rdy(port))
|
|
keepgoing |= mpc52xx_uart_int_tx_chars(port);
|
|
keepgoing |= mpc52xx_uart_int_tx_chars(port);
|
|
|
|
|
|
/* Limit number of iteration */
|
|
/* Limit number of iteration */
|
|
@@ -647,36 +780,33 @@ static void
|
|
mpc52xx_console_write(struct console *co, const char *s, unsigned int count)
|
|
mpc52xx_console_write(struct console *co, const char *s, unsigned int count)
|
|
{
|
|
{
|
|
struct uart_port *port = &mpc52xx_uart_ports[co->index];
|
|
struct uart_port *port = &mpc52xx_uart_ports[co->index];
|
|
- struct mpc52xx_psc __iomem *psc = PSC(port);
|
|
|
|
unsigned int i, j;
|
|
unsigned int i, j;
|
|
|
|
|
|
/* Disable interrupts */
|
|
/* Disable interrupts */
|
|
- out_be16(&psc->mpc52xx_psc_imr, 0);
|
|
|
|
|
|
+ psc_ops->cw_disable_ints(port);
|
|
|
|
|
|
/* Wait the TX buffer to be empty */
|
|
/* Wait the TX buffer to be empty */
|
|
j = 5000000; /* Maximum wait */
|
|
j = 5000000; /* Maximum wait */
|
|
- while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP) &&
|
|
|
|
- --j)
|
|
|
|
|
|
+ while (!mpc52xx_uart_tx_empty(port) && --j)
|
|
udelay(1);
|
|
udelay(1);
|
|
|
|
|
|
/* Write all the chars */
|
|
/* Write all the chars */
|
|
for (i = 0; i < count; i++, s++) {
|
|
for (i = 0; i < count; i++, s++) {
|
|
/* Line return handling */
|
|
/* Line return handling */
|
|
if (*s == '\n')
|
|
if (*s == '\n')
|
|
- out_8(&psc->mpc52xx_psc_buffer_8, '\r');
|
|
|
|
|
|
+ psc_ops->write_char(port, '\r');
|
|
|
|
|
|
/* Send the char */
|
|
/* Send the char */
|
|
- out_8(&psc->mpc52xx_psc_buffer_8, *s);
|
|
|
|
|
|
+ psc_ops->write_char(port, *s);
|
|
|
|
|
|
/* Wait the TX buffer to be empty */
|
|
/* Wait the TX buffer to be empty */
|
|
j = 20000; /* Maximum wait */
|
|
j = 20000; /* Maximum wait */
|
|
- while (!(in_be16(&psc->mpc52xx_psc_status) &
|
|
|
|
- MPC52xx_PSC_SR_TXEMP) && --j)
|
|
|
|
|
|
+ while (!mpc52xx_uart_tx_empty(port) && --j)
|
|
udelay(1);
|
|
udelay(1);
|
|
}
|
|
}
|
|
|
|
|
|
/* Restore interrupt state */
|
|
/* Restore interrupt state */
|
|
- out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask);
|
|
|
|
|
|
+ psc_ops->cw_restore_ints(port);
|
|
}
|
|
}
|
|
|
|
|
|
#if !defined(CONFIG_PPC_MERGE)
|
|
#if !defined(CONFIG_PPC_MERGE)
|
|
@@ -721,7 +851,7 @@ mpc52xx_console_setup(struct console *co, char *options)
|
|
{
|
|
{
|
|
struct uart_port *port = &mpc52xx_uart_ports[co->index];
|
|
struct uart_port *port = &mpc52xx_uart_ports[co->index];
|
|
struct device_node *np = mpc52xx_uart_nodes[co->index];
|
|
struct device_node *np = mpc52xx_uart_nodes[co->index];
|
|
- unsigned int ipb_freq;
|
|
|
|
|
|
+ unsigned int uartclk;
|
|
struct resource res;
|
|
struct resource res;
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
@@ -753,17 +883,16 @@ mpc52xx_console_setup(struct console *co, char *options)
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
- /* Search for bus-frequency property in this node or a parent */
|
|
|
|
- ipb_freq = mpc52xx_find_ipb_freq(np);
|
|
|
|
- if (ipb_freq == 0) {
|
|
|
|
- pr_debug("Could not find IPB bus frequency!\n");
|
|
|
|
|
|
+ uartclk = psc_ops->getuartclk(np);
|
|
|
|
+ if (uartclk == 0) {
|
|
|
|
+ pr_debug("Could not find uart clock frequency!\n");
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
/* Basic port init. Needed since we use some uart_??? func before
|
|
/* Basic port init. Needed since we use some uart_??? func before
|
|
* real init for early access */
|
|
* real init for early access */
|
|
spin_lock_init(&port->lock);
|
|
spin_lock_init(&port->lock);
|
|
- port->uartclk = ipb_freq / 2;
|
|
|
|
|
|
+ port->uartclk = uartclk;
|
|
port->ops = &mpc52xx_uart_ops;
|
|
port->ops = &mpc52xx_uart_ops;
|
|
port->mapbase = res.start;
|
|
port->mapbase = res.start;
|
|
port->membase = ioremap(res.start, sizeof(struct mpc52xx_psc));
|
|
port->membase = ioremap(res.start, sizeof(struct mpc52xx_psc));
|
|
@@ -949,7 +1078,7 @@ static int __devinit
|
|
mpc52xx_uart_of_probe(struct of_device *op, const struct of_device_id *match)
|
|
mpc52xx_uart_of_probe(struct of_device *op, const struct of_device_id *match)
|
|
{
|
|
{
|
|
int idx = -1;
|
|
int idx = -1;
|
|
- unsigned int ipb_freq;
|
|
|
|
|
|
+ unsigned int uartclk;
|
|
struct uart_port *port = NULL;
|
|
struct uart_port *port = NULL;
|
|
struct resource res;
|
|
struct resource res;
|
|
int ret;
|
|
int ret;
|
|
@@ -965,10 +1094,9 @@ mpc52xx_uart_of_probe(struct of_device *op, const struct of_device_id *match)
|
|
pr_debug("Found %s assigned to ttyPSC%x\n",
|
|
pr_debug("Found %s assigned to ttyPSC%x\n",
|
|
mpc52xx_uart_nodes[idx]->full_name, idx);
|
|
mpc52xx_uart_nodes[idx]->full_name, idx);
|
|
|
|
|
|
- /* Search for bus-frequency property in this node or a parent */
|
|
|
|
- ipb_freq = mpc52xx_find_ipb_freq(op->node);
|
|
|
|
- if (ipb_freq == 0) {
|
|
|
|
- dev_dbg(&op->dev, "Could not find IPB bus frequency!\n");
|
|
|
|
|
|
+ uartclk = psc_ops->getuartclk(op->node);
|
|
|
|
+ if (uartclk == 0) {
|
|
|
|
+ dev_dbg(&op->dev, "Could not find uart clock frequency!\n");
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -976,7 +1104,7 @@ mpc52xx_uart_of_probe(struct of_device *op, const struct of_device_id *match)
|
|
port = &mpc52xx_uart_ports[idx];
|
|
port = &mpc52xx_uart_ports[idx];
|
|
|
|
|
|
spin_lock_init(&port->lock);
|
|
spin_lock_init(&port->lock);
|
|
- port->uartclk = ipb_freq / 2;
|
|
|
|
|
|
+ port->uartclk = uartclk;
|
|
port->fifosize = 512;
|
|
port->fifosize = 512;
|
|
port->iotype = UPIO_MEM;
|
|
port->iotype = UPIO_MEM;
|
|
port->flags = UPF_BOOT_AUTOCONF |
|
|
port->flags = UPF_BOOT_AUTOCONF |
|