From e2651647080930a1846196c3b79f4de662100388 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 20 Jan 2011 21:24:03 +0900 Subject: [PATCH] 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 --- drivers/serial/sh-sci.c | 48 ++++++++++++++++++++++++++++++++--------- 1 file 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) 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) -- 2.34.1