diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 44d5bd10702b822a2d1607e58245a6e6bb498ab6..cf2c78079c0d695e9230b81647ce5c4f66238256 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) return NULL; } -static void sci_release_port(struct uart_port *port) +static inline unsigned long sci_port_size(struct uart_port *port) { - /* Nothing here yet .. */ + /* + * Pick an arbitrary size that encapsulates all of the base + * registers by default. This can be optimized later, or derived + * from platform resource data at such a time that ports begin to + * behave more erratically. + */ + return 64; } -static int sci_request_port(struct uart_port *port) +static void sci_release_port(struct uart_port *port) { - /* Nothing here yet .. */ - return 0; + if (port->flags & UPF_IOREMAP) { + iounmap(port->membase); + port->membase = NULL; + } + + release_mem_region(port->mapbase, sci_port_size(port)); } -static void sci_config_port(struct uart_port *port, int flags) +static int sci_request_port(struct uart_port *port) { - struct sci_port *s = to_sci_port(port); + unsigned long size = sci_port_size(port); + struct resource *res; - port->type = s->cfg->type; + res = request_mem_region(port->mapbase, size, sci_type(port)); + if (unlikely(res == NULL)) + return -EBUSY; if (port->flags & UPF_IOREMAP) { - port->membase = ioremap_nocache(port->mapbase, 0x40); - if (unlikely(!port->membase)) + port->membase = ioremap_nocache(port->mapbase, size); + if (unlikely(!port->membase)) { dev_err(port->dev, "can't remap port#%d\n", port->line); + release_resource(res); + return -ENXIO; + } } else { /* * 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) */ port->membase = (void __iomem *)port->mapbase; } + + return 0; +} + +static void sci_config_port(struct uart_port *port, int flags) +{ + if (flags & UART_CONFIG_TYPE) { + struct sci_port *sport = to_sci_port(port); + + port->type = sport->cfg->type; + sci_request_port(port); + } } static int sci_verify_port(struct uart_port *port, struct serial_struct *ser)