|
@@ -48,6 +48,7 @@
|
|
|
#ifdef CONFIG_SERIAL_8250
|
|
|
#include <linux/serial_core.h>
|
|
|
#include <linux/serial_8250.h>
|
|
|
+#include <linux/serial_reg.h>
|
|
|
#endif
|
|
|
|
|
|
#include <linux/netdevice.h>
|
|
@@ -1151,13 +1152,41 @@ static int ioc3_is_menet(struct pci_dev *pdev)
|
|
|
* Also look in ip27-pci.c:pci_fixup_ioc3() for some comments on working
|
|
|
* around ioc3 oddities in this respect.
|
|
|
*
|
|
|
- * The IOC3 serials use a 22MHz clock rate with an additional divider by 3.
|
|
|
+ * The IOC3 serials use a 22MHz clock rate with an additional divider which
|
|
|
+ * can be programmed in the SCR register if the DLAB bit is set.
|
|
|
+ *
|
|
|
+ * Register to interrupt zero because we share the interrupt with
|
|
|
+ * the serial driver which we don't properly support yet.
|
|
|
+ *
|
|
|
+ * Can't use UPF_IOREMAP as the whole of IOC3 resources have already been
|
|
|
+ * registered.
|
|
|
*/
|
|
|
+static void __devinit ioc3_8250_register(struct ioc3_uartregs __iomem *uart)
|
|
|
+{
|
|
|
+#define COSMISC_CONSTANT 6
|
|
|
+
|
|
|
+ struct uart_port port = {
|
|
|
+ .irq = 0,
|
|
|
+ .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
|
|
|
+ .iotype = UPIO_MEM,
|
|
|
+ .regshift = 0,
|
|
|
+ .uartclk = (22000000 << 1) / COSMISC_CONSTANT,
|
|
|
+
|
|
|
+ .membase = (unsigned char __iomem *) uart,
|
|
|
+ .mapbase = (unsigned long) uart,
|
|
|
+ };
|
|
|
+ unsigned char lcr;
|
|
|
+
|
|
|
+ lcr = uart->iu_lcr;
|
|
|
+ uart->iu_lcr = lcr | UART_LCR_DLAB;
|
|
|
+ uart->iu_scr = COSMISC_CONSTANT,
|
|
|
+ uart->iu_lcr = lcr;
|
|
|
+ uart->iu_lcr;
|
|
|
+ serial8250_register_port(&port);
|
|
|
+}
|
|
|
|
|
|
static void __devinit ioc3_serial_probe(struct pci_dev *pdev, struct ioc3 *ioc3)
|
|
|
{
|
|
|
- struct uart_port port;
|
|
|
-
|
|
|
/*
|
|
|
* We need to recognice and treat the fourth MENET serial as it
|
|
|
* does not have an SuperIO chip attached to it, therefore attempting
|
|
@@ -1171,24 +1200,35 @@ static void __devinit ioc3_serial_probe(struct pci_dev *pdev, struct ioc3 *ioc3)
|
|
|
return;
|
|
|
|
|
|
/*
|
|
|
- * Register to interrupt zero because we share the interrupt with
|
|
|
- * the serial driver which we don't properly support yet.
|
|
|
- *
|
|
|
- * Can't use UPF_IOREMAP as the whole of IOC3 resources have already
|
|
|
- * been registered.
|
|
|
+ * Switch IOC3 to PIO mode. It probably already was but let's be
|
|
|
+ * paranoid
|
|
|
*/
|
|
|
- memset(&port, 0, sizeof(port));
|
|
|
- port.irq = 0;
|
|
|
- port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
|
|
|
- port.iotype = UPIO_MEM;
|
|
|
- port.regshift = 0;
|
|
|
- port.uartclk = 22000000 / 3;
|
|
|
-
|
|
|
- port.membase = (unsigned char *) &ioc3->sregs.uarta;
|
|
|
- serial8250_register_port(&port);
|
|
|
-
|
|
|
- port.membase = (unsigned char *) &ioc3->sregs.uartb;
|
|
|
- serial8250_register_port(&port);
|
|
|
+ ioc3->gpcr_s = GPCR_UARTA_MODESEL | GPCR_UARTB_MODESEL;
|
|
|
+ ioc3->gpcr_s;
|
|
|
+ ioc3->gppr_6 = 0;
|
|
|
+ ioc3->gppr_6;
|
|
|
+ ioc3->gppr_7 = 0;
|
|
|
+ ioc3->gppr_7;
|
|
|
+ ioc3->sscr_a = ioc3->sscr_a & ~SSCR_DMA_EN;
|
|
|
+ ioc3->sscr_a;
|
|
|
+ ioc3->sscr_b = ioc3->sscr_b & ~SSCR_DMA_EN;
|
|
|
+ ioc3->sscr_b;
|
|
|
+ /* Disable all SA/B interrupts except for SA/B_INT in SIO_IEC. */
|
|
|
+ ioc3->sio_iec &= ~ (SIO_IR_SA_TX_MT | SIO_IR_SA_RX_FULL |
|
|
|
+ SIO_IR_SA_RX_HIGH | SIO_IR_SA_RX_TIMER |
|
|
|
+ SIO_IR_SA_DELTA_DCD | SIO_IR_SA_DELTA_CTS |
|
|
|
+ SIO_IR_SA_TX_EXPLICIT | SIO_IR_SA_MEMERR);
|
|
|
+ ioc3->sio_iec |= SIO_IR_SA_INT;
|
|
|
+ ioc3->sscr_a = 0;
|
|
|
+ ioc3->sio_iec &= ~ (SIO_IR_SB_TX_MT | SIO_IR_SB_RX_FULL |
|
|
|
+ SIO_IR_SB_RX_HIGH | SIO_IR_SB_RX_TIMER |
|
|
|
+ SIO_IR_SB_DELTA_DCD | SIO_IR_SB_DELTA_CTS |
|
|
|
+ SIO_IR_SB_TX_EXPLICIT | SIO_IR_SB_MEMERR);
|
|
|
+ ioc3->sio_iec |= SIO_IR_SB_INT;
|
|
|
+ ioc3->sscr_b = 0;
|
|
|
+
|
|
|
+ ioc3_8250_register(&ioc3->sregs.uarta);
|
|
|
+ ioc3_8250_register(&ioc3->sregs.uartb);
|
|
|
}
|
|
|
#endif
|
|
|
|