Commit d8b3edf1 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://bk.arm.linux.org.uk/linux-2.6-serial

into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents 340fc58c 0dbd84c6
This diff is collapsed.
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
#include <linux/config.h> #include <linux/config.h>
int serial8250_register_port(struct uart_port *);
void serial8250_unregister_port(int line);
void serial8250_get_irq_map(unsigned int *map); void serial8250_get_irq_map(unsigned int *map);
void serial8250_suspend_port(int line); void serial8250_suspend_port(int line);
void serial8250_resume_port(int line); void serial8250_resume_port(int line);
...@@ -38,14 +40,16 @@ struct old_serial_port { ...@@ -38,14 +40,16 @@ struct old_serial_port {
*/ */
struct serial8250_config { struct serial8250_config {
const char *name; const char *name;
unsigned int fifo_size; unsigned short fifo_size;
unsigned int tx_loadsz; unsigned short tx_loadsz;
unsigned char fcr;
unsigned int flags; unsigned int flags;
}; };
#define UART_CAP_FIFO (1 << 8) /* UART has FIFO */ #define UART_CAP_FIFO (1 << 8) /* UART has FIFO */
#define UART_CAP_EFR (1 << 9) /* UART has EFR */ #define UART_CAP_EFR (1 << 9) /* UART has EFR */
#define UART_CAP_SLEEP (1 << 10) /* UART has IER sleep */ #define UART_CAP_SLEEP (1 << 10) /* UART has IER sleep */
#define UART_CAP_AFE (1 << 11) /* MCR-based hw flow control */
#undef SERIAL_DEBUG_PCI #undef SERIAL_DEBUG_PCI
......
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/tty.h> #include <linux/tty.h>
#include <linux/serial.h>
#include <linux/serial_core.h> #include <linux/serial_core.h>
#include <linux/8250_pci.h> #include <linux/8250_pci.h>
...@@ -75,7 +74,7 @@ struct pci_serial_quirk { ...@@ -75,7 +74,7 @@ struct pci_serial_quirk {
u32 subdevice; u32 subdevice;
int (*init)(struct pci_dev *dev); int (*init)(struct pci_dev *dev);
int (*setup)(struct pci_dev *dev, struct pci_board *board, int (*setup)(struct pci_dev *dev, struct pci_board *board,
struct serial_struct *req, int idx); struct uart_port *port, int idx);
void (*exit)(struct pci_dev *dev); void (*exit)(struct pci_dev *dev);
}; };
...@@ -100,34 +99,32 @@ static void moan_device(const char *str, struct pci_dev *dev) ...@@ -100,34 +99,32 @@ static void moan_device(const char *str, struct pci_dev *dev)
} }
static int static int
setup_port(struct pci_dev *dev, struct serial_struct *req, setup_port(struct pci_dev *dev, struct uart_port *port,
int bar, int offset, int regshift) int bar, int offset, int regshift)
{ {
struct serial_private *priv = pci_get_drvdata(dev); struct serial_private *priv = pci_get_drvdata(dev);
unsigned long port, len; unsigned long base, len;
if (bar >= PCI_NUM_BAR_RESOURCES) if (bar >= PCI_NUM_BAR_RESOURCES)
return -EINVAL; return -EINVAL;
if (pci_resource_flags(dev, bar) & IORESOURCE_MEM) { if (pci_resource_flags(dev, bar) & IORESOURCE_MEM) {
port = pci_resource_start(dev, bar); base = pci_resource_start(dev, bar);
len = pci_resource_len(dev, bar); len = pci_resource_len(dev, bar);
if (!priv->remapped_bar[bar]) if (!priv->remapped_bar[bar])
priv->remapped_bar[bar] = ioremap(port, len); priv->remapped_bar[bar] = ioremap(base, len);
if (!priv->remapped_bar[bar]) if (!priv->remapped_bar[bar])
return -ENOMEM; return -ENOMEM;
req->io_type = UPIO_MEM; port->iotype = UPIO_MEM;
req->iomap_base = port + offset; port->mapbase = base + offset;
req->iomem_base = priv->remapped_bar[bar] + offset; port->membase = priv->remapped_bar[bar] + offset;
req->iomem_reg_shift = regshift; port->regshift = regshift;
} else { } else {
port = pci_resource_start(dev, bar) + offset; base = pci_resource_start(dev, bar) + offset;
req->io_type = UPIO_PORT; port->iotype = UPIO_PORT;
req->port = port; port->iobase = base;
if (HIGH_BITS_OFFSET)
req->port_high = port >> HIGH_BITS_OFFSET;
} }
return 0; return 0;
} }
...@@ -138,7 +135,7 @@ setup_port(struct pci_dev *dev, struct serial_struct *req, ...@@ -138,7 +135,7 @@ setup_port(struct pci_dev *dev, struct serial_struct *req,
*/ */
static int static int
afavlab_setup(struct pci_dev *dev, struct pci_board *board, afavlab_setup(struct pci_dev *dev, struct pci_board *board,
struct serial_struct *req, int idx) struct uart_port *port, int idx)
{ {
unsigned int bar, offset = board->first_offset; unsigned int bar, offset = board->first_offset;
...@@ -150,7 +147,7 @@ afavlab_setup(struct pci_dev *dev, struct pci_board *board, ...@@ -150,7 +147,7 @@ afavlab_setup(struct pci_dev *dev, struct pci_board *board,
offset += (idx - 4) * board->uart_offset; offset += (idx - 4) * board->uart_offset;
} }
return setup_port(dev, req, bar, offset, board->reg_shift); return setup_port(dev, port, bar, offset, board->reg_shift);
} }
/* /*
...@@ -191,7 +188,7 @@ static int __devinit pci_hp_diva_init(struct pci_dev *dev) ...@@ -191,7 +188,7 @@ static int __devinit pci_hp_diva_init(struct pci_dev *dev)
*/ */
static int static int
pci_hp_diva_setup(struct pci_dev *dev, struct pci_board *board, pci_hp_diva_setup(struct pci_dev *dev, struct pci_board *board,
struct serial_struct *req, int idx) struct uart_port *port, int idx)
{ {
unsigned int offset = board->first_offset; unsigned int offset = board->first_offset;
unsigned int bar = FL_GET_BASE(board->flags); unsigned int bar = FL_GET_BASE(board->flags);
...@@ -213,7 +210,7 @@ pci_hp_diva_setup(struct pci_dev *dev, struct pci_board *board, ...@@ -213,7 +210,7 @@ pci_hp_diva_setup(struct pci_dev *dev, struct pci_board *board,
offset += idx * board->uart_offset; offset += idx * board->uart_offset;
return setup_port(dev, req, bar, offset, board->reg_shift); return setup_port(dev, port, bar, offset, board->reg_shift);
} }
/* /*
...@@ -309,7 +306,7 @@ static void __devexit pci_plx9050_exit(struct pci_dev *dev) ...@@ -309,7 +306,7 @@ static void __devexit pci_plx9050_exit(struct pci_dev *dev)
/* SBS Technologies Inc. PMC-OCTPRO and P-OCTAL cards */ /* SBS Technologies Inc. PMC-OCTPRO and P-OCTAL cards */
static int static int
sbs_setup(struct pci_dev *dev, struct pci_board *board, sbs_setup(struct pci_dev *dev, struct pci_board *board,
struct serial_struct *req, int idx) struct uart_port *port, int idx)
{ {
unsigned int bar, offset = board->first_offset; unsigned int bar, offset = board->first_offset;
...@@ -324,7 +321,7 @@ sbs_setup(struct pci_dev *dev, struct pci_board *board, ...@@ -324,7 +321,7 @@ sbs_setup(struct pci_dev *dev, struct pci_board *board,
} else /* we have only 8 ports on PMC-OCTALPRO */ } else /* we have only 8 ports on PMC-OCTALPRO */
return 1; return 1;
return setup_port(dev, req, bar, offset, board->reg_shift); return setup_port(dev, port, bar, offset, board->reg_shift);
} }
/* /*
...@@ -522,7 +519,7 @@ static int __devinit pci_timedia_init(struct pci_dev *dev) ...@@ -522,7 +519,7 @@ static int __devinit pci_timedia_init(struct pci_dev *dev)
*/ */
static int static int
pci_timedia_setup(struct pci_dev *dev, struct pci_board *board, pci_timedia_setup(struct pci_dev *dev, struct pci_board *board,
struct serial_struct *req, int idx) struct uart_port *port, int idx)
{ {
unsigned int bar = 0, offset = board->first_offset; unsigned int bar = 0, offset = board->first_offset;
...@@ -547,7 +544,7 @@ pci_timedia_setup(struct pci_dev *dev, struct pci_board *board, ...@@ -547,7 +544,7 @@ pci_timedia_setup(struct pci_dev *dev, struct pci_board *board,
bar = idx - 2; bar = idx - 2;
} }
return setup_port(dev, req, bar, offset, board->reg_shift); return setup_port(dev, port, bar, offset, board->reg_shift);
} }
/* /*
...@@ -555,7 +552,7 @@ pci_timedia_setup(struct pci_dev *dev, struct pci_board *board, ...@@ -555,7 +552,7 @@ pci_timedia_setup(struct pci_dev *dev, struct pci_board *board,
*/ */
static int static int
titan_400l_800l_setup(struct pci_dev *dev, struct pci_board *board, titan_400l_800l_setup(struct pci_dev *dev, struct pci_board *board,
struct serial_struct *req, int idx) struct uart_port *port, int idx)
{ {
unsigned int bar, offset = board->first_offset; unsigned int bar, offset = board->first_offset;
...@@ -571,7 +568,7 @@ titan_400l_800l_setup(struct pci_dev *dev, struct pci_board *board, ...@@ -571,7 +568,7 @@ titan_400l_800l_setup(struct pci_dev *dev, struct pci_board *board,
offset = (idx - 2) * board->uart_offset; offset = (idx - 2) * board->uart_offset;
} }
return setup_port(dev, req, bar, offset, board->reg_shift); return setup_port(dev, port, bar, offset, board->reg_shift);
} }
static int __devinit pci_xircom_init(struct pci_dev *dev) static int __devinit pci_xircom_init(struct pci_dev *dev)
...@@ -582,7 +579,7 @@ static int __devinit pci_xircom_init(struct pci_dev *dev) ...@@ -582,7 +579,7 @@ static int __devinit pci_xircom_init(struct pci_dev *dev)
static int static int
pci_default_setup(struct pci_dev *dev, struct pci_board *board, pci_default_setup(struct pci_dev *dev, struct pci_board *board,
struct serial_struct *req, int idx) struct uart_port *port, int idx)
{ {
unsigned int bar, offset = board->first_offset, maxnr; unsigned int bar, offset = board->first_offset, maxnr;
...@@ -598,7 +595,7 @@ pci_default_setup(struct pci_dev *dev, struct pci_board *board, ...@@ -598,7 +595,7 @@ pci_default_setup(struct pci_dev *dev, struct pci_board *board,
if (board->flags & FL_REGION_SZ_CAP && idx >= maxnr) if (board->flags & FL_REGION_SZ_CAP && idx >= maxnr)
return 1; return 1;
return setup_port(dev, req, bar, offset, board->reg_shift); return setup_port(dev, port, bar, offset, board->reg_shift);
} }
/* This should be in linux/pci_ids.h */ /* This should be in linux/pci_ids.h */
...@@ -1610,7 +1607,6 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent) ...@@ -1610,7 +1607,6 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
struct serial_private *priv; struct serial_private *priv;
struct pci_board *board, tmp; struct pci_board *board, tmp;
struct pci_serial_quirk *quirk; struct pci_serial_quirk *quirk;
struct serial_struct serial_req;
int rc, nr_ports, i; int rc, nr_ports, i;
if (ent->driver_data >= ARRAY_SIZE(pci_boards)) { if (ent->driver_data >= ARRAY_SIZE(pci_boards)) {
...@@ -1690,19 +1686,22 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent) ...@@ -1690,19 +1686,22 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
pci_set_drvdata(dev, priv); pci_set_drvdata(dev, priv);
for (i = 0; i < nr_ports; i++) { for (i = 0; i < nr_ports; i++) {
memset(&serial_req, 0, sizeof(serial_req)); struct uart_port serial_port;
serial_req.flags = UPF_SKIP_TEST | UPF_AUTOPROBE | memset(&serial_port, 0, sizeof(struct uart_port));
UPF_SHARE_IRQ;
serial_req.baud_base = board->base_baud; serial_port.flags = UPF_SKIP_TEST | UPF_AUTOPROBE |
serial_req.irq = get_pci_irq(dev, board, i); UPF_SHARE_IRQ;
if (quirk->setup(dev, board, &serial_req, i)) serial_port.uartclk = board->base_baud * 16;
serial_port.irq = get_pci_irq(dev, board, i);
serial_port.dev = &dev->dev;
if (quirk->setup(dev, board, &serial_port, i))
break; break;
#ifdef SERIAL_DEBUG_PCI #ifdef SERIAL_DEBUG_PCI
printk("Setup PCI port: port %x, irq %d, type %d\n", printk("Setup PCI port: port %x, irq %d, type %d\n",
serial_req.port, serial_req.irq, serial_req.io_type); serial_port.iobase, serial_port.irq, serial_port.iotype);
#endif #endif
priv->line[i] = register_serial(&serial_req); priv->line[i] = serial8250_register_port(&serial_port);
if (priv->line[i] < 0) { if (priv->line[i] < 0) {
printk(KERN_WARNING "Couldn't register serial port %s: %d\n", pci_name(dev), priv->line[i]); printk(KERN_WARNING "Couldn't register serial port %s: %d\n", pci_name(dev), priv->line[i]);
break; break;
...@@ -1732,7 +1731,7 @@ static void __devexit pciserial_remove_one(struct pci_dev *dev) ...@@ -1732,7 +1731,7 @@ static void __devexit pciserial_remove_one(struct pci_dev *dev)
int i; int i;
for (i = 0; i < priv->nr; i++) for (i = 0; i < priv->nr; i++)
unregister_serial(priv->line[i]); serial8250_unregister_port(priv->line[i]);
for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) { for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) {
if (priv->remapped_bar[i]) if (priv->remapped_bar[i])
......
...@@ -2225,6 +2225,15 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port) ...@@ -2225,6 +2225,15 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
*/ */
tty_register_device(drv->tty_driver, port->line, port->dev); tty_register_device(drv->tty_driver, port->line, port->dev);
/*
* If this driver supports console, and it hasn't been
* successfully registered yet, try to re-register it.
* It may be that the port was not available.
*/
if (port->type != PORT_UNKNOWN &&
port->cons && !(port->cons->flags & CON_ENABLED))
register_console(port->cons);
out: out:
up(&port_sem); up(&port_sem);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment