Encapsulates the existing array of uint for signal mapping and adds baudrate group selection. Signed-off-by: Martin Fuzzey <mfuzzey@xxxxxxxxx> --- arch/mips/sni/a20r.c | 15 ++++++++---- drivers/serial/sc26xx.c | 49 +++++++++++++++++++++++++++++++++++---- include/linux/serial_sc2xxx.h | 52 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+), 9 deletions(-) create mode 100644 include/linux/serial_sc2xxx.h diff --git a/arch/mips/sni/a20r.c b/arch/mips/sni/a20r.c index e698089..2fbbb65 100644 --- a/arch/mips/sni/a20r.c +++ b/arch/mips/sni/a20r.c @@ -12,6 +12,7 @@ #include <linux/interrupt.h> #include <linux/platform_device.h> #include <linux/serial_8250.h> +#include <linux/serial_sc2xxx.h> #include <asm/sni.h> #include <asm/time.h> @@ -117,10 +118,14 @@ static struct resource sc26xx_rsrc[] = { } }; -static unsigned int sc26xx_data[2] = { - /* DTR | RTS | DSR | CTS | DCD | RI */ - (8 << 0) | (4 << 4) | (6 << 8) | (0 << 12) | (6 << 16) | (0 << 20), - (3 << 0) | (2 << 4) | (1 << 8) | (2 << 12) | (3 << 16) | (4 << 20) +static struct plat_serial_sc2xxx sc26xx_data = { + .signal_map = { + /* DTR | RTS | DSR | CTS | DCD | RI */ + (8 << 0) | (4 << 4) | (6 << 8) | (0 << 12) | (6 << 16) | (0 << 20), + (3 << 0) | (2 << 4) | (1 << 8) | (2 << 12) | (3 << 16) | (4 << 20) + }, + .baud_mode = 1, + .baud_group = 2, }; static struct platform_device sc26xx_pdev = { @@ -128,7 +133,7 @@ static struct platform_device sc26xx_pdev = { .num_resources = ARRAY_SIZE(sc26xx_rsrc), .resource = sc26xx_rsrc, .dev = { - .platform_data = sc26xx_data, + .platform_data = &sc26xx_data, } }; diff --git a/drivers/serial/sc26xx.c b/drivers/serial/sc26xx.c index 053520d..09e73a3 100644 --- a/drivers/serial/sc26xx.c +++ b/drivers/serial/sc26xx.c @@ -22,6 +22,7 @@ #include <linux/platform_device.h> #include <linux/irq.h> #include <linux/io.h> +#include <linux/serial_sc2xxx.h> #if defined(CONFIG_MAGIC_SYSRQ) #define SUPPORT_SYSRQ @@ -171,6 +172,10 @@ static struct chip_def chip_2892 = { .init_mr1 = (1 << 6), }; +static const struct chip_def *chips[] = { + &chip_26xx, + &chip_2892 +}; static struct uart_sc26xx_port *driver_info(struct uart_port *port) { @@ -753,9 +758,17 @@ static void __devinit sc26xx_init_masks(struct uart_sc26xx_port *up, static int __devinit init_baudgroup(struct uart_sc26xx_port *up) { + struct plat_serial_sc2xxx *pdata = up->port[0].dev->platform_data; + u8 baud_mode = up->chip->default_baud_mode; u8 baud_group = up->chip->default_baud_group; + if (pdata->baud_mode > 0) + baud_mode = pdata->baud_mode - 1; + + if (pdata->baud_group > 0) + baud_group = pdata->baud_group - 1; + if (baud_mode > up->chip->max_baud_mode) { printk(KERN_ERR "Baud mode %d not supported for %s\n", baud_mode, up->chip->name); @@ -779,6 +792,20 @@ static int __devinit init_baudgroup(struct uart_sc26xx_port *up) return 0; } +static const struct chip_def * __devinit chip_by_name(const char *name) +{ + int i; + const struct chip_def *chip; + + for (i = 0; i < ARRAY_SIZE(chips); i++) { + chip = chips[i]; + if (!strcmp(chip->name, name)) + return chip; + } + + return NULL; +} + static const struct chip_def * __devinit detect_chip_type( struct uart_sc26xx_port *up) { @@ -809,9 +836,14 @@ static int __devinit sc26xx_probe(struct platform_device *dev) { struct resource *res, *irq_res; struct uart_sc26xx_port *up; - unsigned int *sc26xx_data = dev->dev.platform_data; + struct plat_serial_sc2xxx *pdata = dev->dev.platform_data; int err; + if (!pdata) { + dev_err(&dev->dev, "No platform data\n"); + return -EINVAL; + } + res = platform_get_resource(dev, IORESOURCE_MEM, 0); if (!res) return -ENODEV; @@ -836,16 +868,25 @@ static int __devinit sc26xx_probe(struct platform_device *dev) up->port[0].dev = &dev->dev; - sc26xx_init_masks(up, 0, sc26xx_data[0]); + sc26xx_init_masks(up, 0, pdata->signal_map[0]); sc26xx_port = &up->port[0]; memcpy(&up->port[1], &up->port[0], sizeof(up->port[0])); up->port[1].line = 1; - sc26xx_init_masks(up, 1, sc26xx_data[1]); + sc26xx_init_masks(up, 1, pdata->signal_map[1]); + + if (pdata->chip_name) + up->chip = chip_by_name(pdata->chip_name); + if (!up->chip) { + if (pdata->chip_name) + dev_warn(&dev->dev, + "Unknown chip %s requested - use autodetect\n", + pdata->chip_name); + up->chip = detect_chip_type(up); + } - up->chip = detect_chip_type(up); err = init_baudgroup(up); if (err) goto out_free_port; diff --git a/include/linux/serial_sc2xxx.h b/include/linux/serial_sc2xxx.h new file mode 100644 index 0000000..d93977f --- /dev/null +++ b/include/linux/serial_sc2xxx.h @@ -0,0 +1,52 @@ +/* + * + * Copyright (C) 2009 Martin Fuzzey + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + + +#ifndef _LINUX_SERIAL_SC26XX_H +#define _LINUX_SERIAL_SC26XX_H 1 + + +/** + * struct plat_sc2xxx - Philips UART platform data + * @signal_map: Hardware signal mapping (see below) + * + * @chip_name: One of "SC26xx", "SC2892" or NULL for autodetect + * + * @baud_mode: Baudrate mode + 1 (1,2,3) must be 1 for SC26xx see + * datasheet or baud_rates[] in driver code for available + * baudrates in each mode + * 0 = use driver default + * + * @baud_group: Baudrate group + 1 (1, 2) within mode + * 0 = use driver default + * + * For each port signal_map is a bitfield defined as follows: + * bits 0-3 DTR + * bits 4-7 RTS + * bits 8-11 DSR + * bits 12-15 CTS + * bits 16-19 DCD + * bits 20-23 RI + * + * Value of each field is 1 + corresponding IP/OP pin or 0 if not connected + * Eg: + * (3 << 0) | (1 << 4) | (3 << 8) | (1 << 12) | (4 << 16) | (0 << 20), + * => + * DTR=OP2, RTS=OP0, DSR=IP2, CTS=IP0, DCD=IP3, RI=NC + * + **/ +struct plat_serial_sc2xxx { + unsigned int signal_map[2]; + const char *chip_name; + u8 baud_mode; + u8 baud_group; +}; + +#endif -- To unsubscribe from this list: send the line "unsubscribe linux-serial" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html