serial: imx: bit &/| confusion
[safe/jmp/linux-2.6] / drivers / serial / pmac_zilog.c
index be8d757..683e66f 100644 (file)
@@ -88,6 +88,16 @@ MODULE_LICENSE("GPL");
 
 #define PWRDBG(fmt, arg...)    printk(KERN_DEBUG fmt , ## arg)
 
+#ifdef CONFIG_SERIAL_PMACZILOG_TTYS
+#define PMACZILOG_MAJOR                TTY_MAJOR
+#define PMACZILOG_MINOR                64
+#define PMACZILOG_NAME         "ttyS"
+#else
+#define PMACZILOG_MAJOR                204
+#define PMACZILOG_MINOR                192
+#define PMACZILOG_NAME         "ttyPZ"
+#endif
+
 
 /*
  * For the sake of early serial console, we can do a pre-probe
@@ -99,9 +109,10 @@ static DEFINE_MUTEX(pmz_irq_mutex);
 
 static struct uart_driver pmz_uart_reg = {
        .owner          =       THIS_MODULE,
-       .driver_name    =       "ttyS",
-       .dev_name       =       "ttyS",
-       .major          =       TTY_MAJOR,
+       .driver_name    =       PMACZILOG_NAME,
+       .dev_name       =       PMACZILOG_NAME,
+       .major          =       PMACZILOG_MAJOR,
+       .minor          =       PMACZILOG_MINOR,
 };
 
 
@@ -231,12 +242,12 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap)
        }
 
        /* Sanity check, make sure the old bug is no longer happening */
-       if (uap->port.info == NULL || uap->port.info->tty == NULL) {
+       if (uap->port.state == NULL || uap->port.state->port.tty == NULL) {
                WARN_ON(1);
                (void)read_zsdata(uap);
                return NULL;
        }
-       tty = uap->port.info->tty;
+       tty = uap->port.state->port.tty;
 
        while (1) {
                error = 0;
@@ -358,7 +369,7 @@ static void pmz_status_handle(struct uart_pmac_port *uap)
                        uart_handle_cts_change(&uap->port,
                                               !(status & CTS));
 
-               wake_up_interruptible(&uap->port.info->delta_msr_wait);
+               wake_up_interruptible(&uap->port.state->port.delta_msr_wait);
        }
 
        if (status & BRK_ABRT)
@@ -400,6 +411,17 @@ static void pmz_transmit_chars(struct uart_pmac_port *uap)
                goto ack_tx_int;
        }
 
+       /* Under some circumstances, we see interrupts reported for
+        * a closed channel. The interrupt mask in R1 is clear, but
+        * R3 still signals the interrupts and we see them when taking
+        * an interrupt for the other channel (this could be a qemu
+        * bug but since the ESCC doc doesn't specify precsiely whether
+        * R3 interrup status bits are masked by R1 interrupt enable
+        * bits, better safe than sorry). --BenH.
+        */
+       if (!ZS_IS_OPEN(uap))
+               goto ack_tx_int;
+
        if (uap->port.x_char) {
                uap->flags |= PMACZILOG_FLAG_TX_ACTIVE;
                write_zsdata(uap, uap->port.x_char);
@@ -409,9 +431,9 @@ static void pmz_transmit_chars(struct uart_pmac_port *uap)
                return;
        }
 
-       if (uap->port.info == NULL)
+       if (uap->port.state == NULL)
                goto ack_tx_int;
-       xmit = &uap->port.info->xmit;
+       xmit = &uap->port.state->xmit;
        if (uart_circ_empty(xmit)) {
                uart_write_wakeup(&uap->port);
                goto ack_tx_int;
@@ -644,7 +666,7 @@ static void pmz_start_tx(struct uart_port *port)
                port->icount.tx++;
                port->x_char = 0;
        } else {
-               struct circ_buf *xmit = &port->info->xmit;
+               struct circ_buf *xmit = &port->state->xmit;
 
                write_zsdata(uap, xmit->buf[xmit->tail]);
                zssync(uap);
@@ -1372,6 +1394,29 @@ static int pmz_verify_port(struct uart_port *port, struct serial_struct *ser)
        return -EINVAL;
 }
 
+#ifdef CONFIG_CONSOLE_POLL
+
+static int pmz_poll_get_char(struct uart_port *port)
+{
+       struct uart_pmac_port *uap = (struct uart_pmac_port *)port;
+
+       while ((read_zsreg(uap, R0) & Rx_CH_AV) == 0)
+               udelay(5);
+       return read_zsdata(uap);
+}
+
+static void pmz_poll_put_char(struct uart_port *port, unsigned char c)
+{
+       struct uart_pmac_port *uap = (struct uart_pmac_port *)port;
+
+       /* Wait for the transmit buffer to empty. */
+       while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0)
+               udelay(5);
+       write_zsdata(uap, c);
+}
+
+#endif
+
 static struct uart_ops pmz_pops = {
        .tx_empty       =       pmz_tx_empty,
        .set_mctrl      =       pmz_set_mctrl,
@@ -1389,6 +1434,10 @@ static struct uart_ops pmz_pops = {
        .request_port   =       pmz_request_port,
        .config_port    =       pmz_config_port,
        .verify_port    =       pmz_verify_port,
+#ifdef CONFIG_CONSOLE_POLL
+       .poll_get_char  =       pmz_poll_get_char,
+       .poll_put_char  =       pmz_poll_put_char,
+#endif
 };
 
 /*
@@ -1450,14 +1499,14 @@ no_dma:
        /*
         * Detect port type
         */
-       if (device_is_compatible(np, "cobalt"))
+       if (of_device_is_compatible(np, "cobalt"))
                uap->flags |= PMACZILOG_FLAG_IS_INTMODEM;
-       conn = get_property(np, "AAPL,connector", &len);
+       conn = of_get_property(np, "AAPL,connector", &len);
        if (conn && (strcmp(conn, "infrared") == 0))
                uap->flags |= PMACZILOG_FLAG_IS_IRDA;
        uap->port_type = PMAC_SCC_ASYNC;
        /* 1999 Powerbook G3 has slot-names property instead */
-       slots = get_property(np, "slot-names", &len);
+       slots = of_get_property(np, "slot-names", &len);
        if (slots && slots->count > 0) {
                if (strcmp(slots->name, "IrDA") == 0)
                        uap->flags |= PMACZILOG_FLAG_IS_IRDA;
@@ -1471,7 +1520,7 @@ no_dma:
                        of_find_node_by_name(NULL, "i2c-modem");
                if (i2c_modem) {
                        const char* mid =
-                               get_property(i2c_modem, "modem-id", NULL);
+                               of_get_property(i2c_modem, "modem-id", NULL);
                        if (mid) switch(*mid) {
                        case 0x04 :
                        case 0x05 :
@@ -1500,6 +1549,21 @@ no_dma:
        uap->port.type = PORT_PMAC_ZILOG;
        uap->port.flags = 0;
 
+       /*
+        * Fixup for the port on Gatwick for which the device-tree has
+        * missing interrupts. Normally, the macio_dev would contain
+        * fixed up interrupt info, but we use the device-tree directly
+        * here due to early probing so we need the fixup too.
+        */
+       if (uap->port.irq == NO_IRQ &&
+           np->parent && np->parent->parent &&
+           of_device_is_compatible(np->parent->parent, "gatwick")) {
+               /* IRQs on gatwick are offset by 64 */
+               uap->port.irq = irq_create_mapping(NULL, 64 + 15);
+               uap->tx_dma_irq = irq_create_mapping(NULL, 64 + 4);
+               uap->rx_dma_irq = irq_create_mapping(NULL, 64 + 5);
+       }
+
        /* Setup some valid baud rate information in the register
         * shadows so we don't write crap there before baud rate is
         * first initialized.
@@ -1587,12 +1651,12 @@ static int pmz_suspend(struct macio_dev *mdev, pm_message_t pm_state)
        if (pm_state.event == mdev->ofdev.dev.power.power_state.event)
                return 0;
 
-       pmz_debug("suspend, switching to state %d\n", pm_state);
+       pmz_debug("suspend, switching to state %d\n", pm_state.event);
 
        state = pmz_uart_reg.state + uap->port.line;
 
        mutex_lock(&pmz_irq_mutex);
-       mutex_lock(&state->mutex);
+       mutex_lock(&state->port.mutex);
 
        spin_lock_irqsave(&uap->port.lock, flags);
 
@@ -1623,7 +1687,7 @@ static int pmz_suspend(struct macio_dev *mdev, pm_message_t pm_state)
        /* Shut the chip down */
        pmz_set_scc_power(uap, 0);
 
-       mutex_unlock(&state->mutex);
+       mutex_unlock(&state->port.mutex);
        mutex_unlock(&pmz_irq_mutex);
 
        pmz_debug("suspend, switching complete\n");
@@ -1652,7 +1716,7 @@ static int pmz_resume(struct macio_dev *mdev)
        state = pmz_uart_reg.state + uap->port.line;
 
        mutex_lock(&pmz_irq_mutex);
-       mutex_lock(&state->mutex);
+       mutex_lock(&state->port.mutex);
 
        spin_lock_irqsave(&uap->port.lock, flags);
        if (!ZS_IS_OPEN(uap) && !ZS_IS_CONS(uap)) {
@@ -1684,7 +1748,7 @@ static int pmz_resume(struct macio_dev *mdev)
        }
 
  bail:
-       mutex_unlock(&state->mutex);
+       mutex_unlock(&state->port.mutex);
        mutex_unlock(&pmz_irq_mutex);
 
        /* Right now, we deal with delay by blocking here, I'll be
@@ -1778,7 +1842,7 @@ static void pmz_console_write(struct console *con, const char *s, unsigned int c
 static int __init pmz_console_setup(struct console *co, char *options);
 
 static struct console pmz_console = {
-       .name   =       "ttyS",
+       .name   =       PMACZILOG_NAME,
        .write  =       pmz_console_write,
        .device =       uart_console_device,
        .setup  =       pmz_console_setup,
@@ -1802,7 +1866,6 @@ static int __init pmz_register(void)
        
        pmz_uart_reg.nr = pmz_ports_count;
        pmz_uart_reg.cons = PMACZILOG_CONSOLE;
-       pmz_uart_reg.minor = 64;
 
        /*
         * Register this driver with the serial core