aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2011-01-20 07:24:03 -0500
committerPaul Mundt <lethal@linux-sh.org>2011-01-20 07:24:03 -0500
commite2651647080930a1846196c3b79f4de662100388 (patch)
tree1016690d4c940f0d7715537800adb381f5368ddc /drivers/serial
parente8183a6c6238a192fba32ac47d75fd076ca487a6 (diff)
serial: sh-sci: Handle port memory region reservations.
At the moment the request/release_port ops are no-ops with the port remapping case tied in to the config_port op. This moves the remap logic in to the request_port, balances it with unmapping in the port release, and finally takes care of the mem region reservations. All existing users are of the port autoconf variety, so we follow the example of other drivers that wrap in to the port request by way of the config op in the UART_CONFIG_TYPE case. This is the first step towards fixing up conflicts with multiple users of the same ports, as currently happens between sh-sci and spi_sh_sci. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'drivers/serial')
-rw-r--r--drivers/serial/sh-sci.c48
1 files changed, 38 insertions, 10 deletions
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
index 44d5bd10702b..cf2c78079c0d 100644
--- a/drivers/serial/sh-sci.c
+++ b/drivers/serial/sh-sci.c
@@ -1595,27 +1595,43 @@ static const char *sci_type(struct uart_port *port)
1595 return NULL; 1595 return NULL;
1596} 1596}
1597 1597
1598static void sci_release_port(struct uart_port *port) 1598static inline unsigned long sci_port_size(struct uart_port *port)
1599{ 1599{
1600 /* Nothing here yet .. */ 1600 /*
1601 * Pick an arbitrary size that encapsulates all of the base
1602 * registers by default. This can be optimized later, or derived
1603 * from platform resource data at such a time that ports begin to
1604 * behave more erratically.
1605 */
1606 return 64;
1601} 1607}
1602 1608
1603static int sci_request_port(struct uart_port *port) 1609static void sci_release_port(struct uart_port *port)
1604{ 1610{
1605 /* Nothing here yet .. */ 1611 if (port->flags & UPF_IOREMAP) {
1606 return 0; 1612 iounmap(port->membase);
1613 port->membase = NULL;
1614 }
1615
1616 release_mem_region(port->mapbase, sci_port_size(port));
1607} 1617}
1608 1618
1609static void sci_config_port(struct uart_port *port, int flags) 1619static int sci_request_port(struct uart_port *port)
1610{ 1620{
1611 struct sci_port *s = to_sci_port(port); 1621 unsigned long size = sci_port_size(port);
1622 struct resource *res;
1612 1623
1613 port->type = s->cfg->type; 1624 res = request_mem_region(port->mapbase, size, sci_type(port));
1625 if (unlikely(res == NULL))
1626 return -EBUSY;
1614 1627
1615 if (port->flags & UPF_IOREMAP) { 1628 if (port->flags & UPF_IOREMAP) {
1616 port->membase = ioremap_nocache(port->mapbase, 0x40); 1629 port->membase = ioremap_nocache(port->mapbase, size);
1617 if (unlikely(!port->membase)) 1630 if (unlikely(!port->membase)) {
1618 dev_err(port->dev, "can't remap port#%d\n", port->line); 1631 dev_err(port->dev, "can't remap port#%d\n", port->line);
1632 release_resource(res);
1633 return -ENXIO;
1634 }
1619 } else { 1635 } else {
1620 /* 1636 /*
1621 * For the simple (and majority of) cases where we don't 1637 * For the simple (and majority of) cases where we don't
@@ -1624,6 +1640,18 @@ static void sci_config_port(struct uart_port *port, int flags)
1624 */ 1640 */
1625 port->membase = (void __iomem *)port->mapbase; 1641 port->membase = (void __iomem *)port->mapbase;
1626 } 1642 }
1643
1644 return 0;
1645}
1646
1647static void sci_config_port(struct uart_port *port, int flags)
1648{
1649 if (flags & UART_CONFIG_TYPE) {
1650 struct sci_port *sport = to_sci_port(port);
1651
1652 port->type = sport->cfg->type;
1653 sci_request_port(port);
1654 }
1627} 1655}
1628 1656
1629static int sci_verify_port(struct uart_port *port, struct serial_struct *ser) 1657static int sci_verify_port(struct uart_port *port, struct serial_struct *ser)