Signed-off-by: michael musset <mickamusset@xxxxxxxxx> --- drivers/tty/serial/max310x.c | 211 +++++++++++++++++++++++++++---------------- 1 file changed, 133 insertions(+), 78 deletions(-) diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index 182549f..81ef694 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c @@ -251,6 +251,8 @@ #define MAX14830_BRGCFG_CLKDIS_BIT (1 << 6) /* Clock Disable */ #define MAX14830_REV_ID (0xb0) +#define MAX_MAX310X 5 + struct max310x_devtype { char name[9]; int nr; @@ -265,7 +267,9 @@ struct max310x_one { }; struct max310x_port { - struct uart_driver uart; + int nr; + int index; +// struct uart_driver uart; struct max310x_devtype *devtype; struct regmap *regmap; struct mutex mutex; @@ -276,11 +280,24 @@ struct max310x_port { struct max310x_one p[0]; }; +static struct uart_driver max310x_uart_driver = { + .owner = THIS_MODULE, + .driver_name = "ttyMAX", + .dev_name = "ttyMAX", + .major = MAX310X_MAJOR, + .minor = MAX310X_MINOR, + .nr = MAX_MAX310X, +}; + +static struct max310x_port *max310xs[MAX_MAX310X]; /* the chips */ +static DEFINE_MUTEX(max310xs_lock); /* race on probe */ +static int uart_driver_registered; + static u8 max310x_port_read(struct uart_port *port, u8 reg) { struct max310x_port *s = dev_get_drvdata(port->dev); unsigned int val = 0; - + printk("max310x_port_read %d\n", s->index); regmap_read(s->regmap, port->iobase + reg, &val); return val; @@ -289,14 +306,14 @@ static u8 max310x_port_read(struct uart_port *port, u8 reg) static void max310x_port_write(struct uart_port *port, u8 reg, u8 val) { struct max310x_port *s = dev_get_drvdata(port->dev); - + printk("max310x_port_write %d\n", s->index); regmap_write(s->regmap, port->iobase + reg, val); } static void max310x_port_update(struct uart_port *port, u8 reg, u8 mask, u8 val) { struct max310x_port *s = dev_get_drvdata(port->dev); - + printk("max310x_port_update %d\n", s->index); regmap_update_bits(s->regmap, port->iobase + reg, mask, val); } @@ -715,13 +732,13 @@ static irqreturn_t max310x_ist(int irq, void *dev_id) { struct max310x_port *s = (struct max310x_port *)dev_id; - if (s->uart.nr > 1) { + if (s->nr > 1) { do { unsigned int val = ~0; WARN_ON_ONCE(regmap_read(s->regmap, MAX310X_GLOBALIRQ_REG, &val)); - val = ((1 << s->uart.nr) - 1) & ~val; + val = ((1 << s->nr) - 1) & ~val; if (!val) break; max310x_port_irq(s, fls(val) - 1); @@ -745,7 +762,8 @@ static void max310x_wq_proc(struct work_struct *ws) static void max310x_start_tx(struct uart_port *port) { struct max310x_one *one = container_of(port, struct max310x_one, port); - + struct max310x_port *s = dev_get_drvdata(port->dev); + printk("max310x_start_tx %d", s->index); if (!work_pending(&one->tx_work)) schedule_work(&one->tx_work); } @@ -753,7 +771,8 @@ static void max310x_start_tx(struct uart_port *port) static unsigned int max310x_tx_empty(struct uart_port *port) { unsigned int lvl, sts; - + struct max310x_port *s = dev_get_drvdata(port->dev); + printk("max310x_tx_empty %d", s->index); lvl = max310x_port_read(port, MAX310X_TXFIFOLVL_REG); sts = max310x_port_read(port, MAX310X_IRQSTS_REG); @@ -914,7 +933,7 @@ static int max310x_startup(struct uart_port *port) { struct max310x_port *s = dev_get_drvdata(port->dev); unsigned int val; - + printk("max310x_startup %d", s->index); s->devtype->power(port, 1); /* Configure MODE1 register */ @@ -1009,8 +1028,8 @@ static int __maybe_unused max310x_suspend(struct device *dev) struct max310x_port *s = dev_get_drvdata(dev); int i; - for (i = 0; i < s->uart.nr; i++) { - uart_suspend_port(&s->uart, &s->p[i].port); + for (i = 0; i < s->nr; i++) { + uart_suspend_port(&max310x_uart_driver, &s->p[i].port); s->devtype->power(&s->p[i].port, 0); } @@ -1022,9 +1041,9 @@ static int __maybe_unused max310x_resume(struct device *dev) struct max310x_port *s = dev_get_drvdata(dev); int i; - for (i = 0; i < s->uart.nr; i++) { + for (i = 0; i < s->nr; i++) { s->devtype->power(&s->p[i].port, 1); - uart_resume_port(&s->uart, &s->p[i].port); + uart_resume_port(&max310x_uart_driver, &s->p[i].port); } return 0; @@ -1081,48 +1100,87 @@ static int max310x_gpio_direction_output(struct gpio_chip *chip, static int max310x_probe(struct device *dev, struct max310x_devtype *devtype, struct regmap *regmap, int irq, unsigned long flags) { - int i, ret, fmin, fmax, freq, uartclk; - struct clk *clk_osc, *clk_xtal; - struct max310x_port *s; - bool xtal = false; + int j,k; + int i, ret, fmin, fmax, freq=0, uartclk; + struct clk *clk_osc, *clk_xtal; + struct max310x_port *s; + bool xtal = false; + int retval = 0; if (IS_ERR(regmap)) return PTR_ERR(regmap); + mutex_lock(&max310xs_lock); + + if (!uart_driver_registered) { + printk("max310x init driver max310X\n"); + uart_driver_registered = 1; + retval = uart_register_driver(&max310x_uart_driver); + if (retval) { + printk(KERN_ERR "max310x Couldn't register max310x uart driver\n"); + mutex_unlock(&max310xs_lock); + return retval; + } + } + for (k = 0; k < MAX_MAX310X; k++) + if (!max310xs[k]) + break; + if (k == MAX_MAX310X) { + dev_warn(dev, "too many MAX310X chips\n"); + mutex_unlock(&max310xs_lock); + return -ENOMEM; + } + printk("max310x index %d\n", k); + + /* Alloc port structure */ - s = devm_kzalloc(dev, sizeof(*s) + + max310xs[k] =s = devm_kzalloc(dev, sizeof(*s) + sizeof(struct max310x_one) * devtype->nr, GFP_KERNEL); + + mutex_unlock(&max310xs_lock); + if (!s) { dev_err(dev, "Error allocating port structure\n"); return -ENOMEM; } - clk_osc = devm_clk_get(dev, "osc"); - clk_xtal = devm_clk_get(dev, "xtal"); - if (!IS_ERR(clk_osc)) { - s->clk = clk_osc; - fmin = 500000; - fmax = 35000000; - } else if (!IS_ERR(clk_xtal)) { - s->clk = clk_xtal; - fmin = 1000000; - fmax = 4000000; - xtal = true; - } else if (PTR_ERR(clk_osc) == -EPROBE_DEFER || - PTR_ERR(clk_xtal) == -EPROBE_DEFER) { - return -EPROBE_DEFER; - } else { - dev_err(dev, "Cannot get clock\n"); - return -EINVAL; + s->index=k; + + if (of_find_property(dev->of_node, "clock-frequency", NULL)){ + of_property_read_u32(dev->of_node, "clock-frequency", &freq); + printk("max310x clock frequency detected %d\n", freq); + } + if(freq!=0){ + fmin = 1000000; + fmax = 4000000; + xtal = 0; + }else{ + clk_osc = devm_clk_get(dev, "osc"); + clk_xtal = devm_clk_get(dev, "xtal"); + if (!IS_ERR(clk_osc)) { + s->clk = clk_osc; + fmin = 500000; + fmax = 35000000; + } else if (!IS_ERR(clk_xtal)) { + s->clk = clk_xtal; + fmin = 1000000; + fmax = 4000000; + xtal = true; + } else if (PTR_ERR(clk_osc) == -EPROBE_DEFER || + PTR_ERR(clk_xtal) == -EPROBE_DEFER) { + return -EPROBE_DEFER; + } else { + dev_err(dev, "Cannot get clock\n"); + return -EINVAL; + } + ret = clk_prepare_enable(s->clk); + if (ret) + return ret; + freq = clk_get_rate(s->clk); } - - ret = clk_prepare_enable(s->clk); - if (ret) - return ret; - - freq = clk_get_rate(s->clk); /* Check frequency limits */ if (freq < fmin || freq > fmax) { + printk("max310x error frequency\n"); ret = -ERANGE; goto out_clk; } @@ -1133,23 +1191,27 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype, /* Check device to ensure we are talking to what we expect */ ret = devtype->detect(dev); - if (ret) + if (ret){ + printk("max310x detection failed\n"); goto out_clk; - + } for (i = 0; i < devtype->nr; i++) { unsigned int offs = i << 5; - /* Reset port */ - regmap_write(s->regmap, MAX310X_MODE2_REG + offs, - MAX310X_MODE2_RST_BIT); - /* Clear port reset */ - regmap_write(s->regmap, MAX310X_MODE2_REG + offs, 0); - /* Wait for port startup */ - do { - regmap_read(s->regmap, - MAX310X_BRGDIVLSB_REG + offs, &ret); - } while (ret != 0x01); + do{ + /* Reset port */ + regmap_write(s->regmap, MAX310X_MODE2_REG + offs, MAX310X_MODE2_RST_BIT); + /* Clear port reset */ + regmap_write(s->regmap, MAX310X_MODE2_REG + offs, 0); + + j=0; + ret=0; + for(j=0;(j<5 && ret!=0x01);j++){ + regmap_read(s->regmap, + MAX310X_BRGDIVLSB_REG + offs, &ret); + } + }while(ret!=0x01); regmap_update_bits(s->regmap, MAX310X_MODE1_REG + offs, MAX310X_MODE1_AUTOSLEEP_BIT, @@ -1157,19 +1219,8 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype, } uartclk = max310x_set_ref_clk(s, freq, xtal); - dev_dbg(dev, "Reference clock set to %i Hz\n", uartclk); - - /* Register UART driver */ - s->uart.owner = THIS_MODULE; - s->uart.dev_name = "ttyMAX"; - s->uart.major = MAX310X_MAJOR; - s->uart.minor = MAX310X_MINOR; - s->uart.nr = devtype->nr; - ret = uart_register_driver(&s->uart); - if (ret) { - dev_err(dev, "Registering UART driver failed\n"); - goto out_clk; - } + printk("max310x Reference clock set to %i Hz\n", uartclk); + s->nr = devtype->nr; #ifdef CONFIG_GPIOLIB /* Setup GPIO cotroller */ @@ -1184,15 +1235,17 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype, s->gpio.ngpio = devtype->nr * 4; s->gpio.can_sleep = 1; ret = gpiochip_add(&s->gpio); - if (ret) + if (ret){ + printk("max310x failed gpio add\n"); goto out_uart; + } #endif mutex_init(&s->mutex); - + printk("max310x devtype nr %d\n", devtype->nr); for (i = 0; i < devtype->nr; i++) { /* Initialize port data */ - s->p[i].port.line = i; + s->p[i].port.line = (k+i); s->p[i].port.dev = dev; s->p[i].port.irq = irq; s->p[i].port.type = PORT_MAX310X; @@ -1217,7 +1270,8 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype, /* Initialize queue for changing mode */ INIT_WORK(&s->p[i].md_work, max310x_md_proc); /* Register port */ - uart_add_one_port(&s->uart, &s->p[i].port); + printk("max310x uart add one port\n"); + uart_add_one_port( &max310x_uart_driver, &s->p[i].port); /* Go to suspend mode */ devtype->power(&s->p[i].port, 0); } @@ -1225,9 +1279,10 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype, /* Setup interrupt */ ret = devm_request_threaded_irq(dev, irq, NULL, max310x_ist, IRQF_ONESHOT | flags, dev_name(dev), s); - if (!ret) + if (!ret){ + printk("max310x add success\n"); return 0; - + } dev_err(dev, "Unable to reguest IRQ %i\n", irq); mutex_destroy(&s->mutex); @@ -1237,7 +1292,7 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype, out_uart: #endif - uart_unregister_driver(&s->uart); + uart_unregister_driver(&max310x_uart_driver); out_clk: clk_disable_unprepare(s->clk); @@ -1254,15 +1309,15 @@ static int max310x_remove(struct device *dev) gpiochip_remove(&s->gpio); #endif - for (i = 0; i < s->uart.nr; i++) { + for (i = 0; i < s->nr; i++) { cancel_work_sync(&s->p[i].tx_work); cancel_work_sync(&s->p[i].md_work); - uart_remove_one_port(&s->uart, &s->p[i].port); + uart_remove_one_port(&max310x_uart_driver, &s->p[i].port); s->devtype->power(&s->p[i].port, 0); } mutex_destroy(&s->mutex); - uart_unregister_driver(&s->uart); + uart_unregister_driver(&max310x_uart_driver); clk_disable_unprepare(s->clk); return 0; @@ -1335,7 +1390,7 @@ static const struct spi_device_id max310x_id_table[] = { }; MODULE_DEVICE_TABLE(spi, max310x_id_table); -static struct spi_driver max310x_uart_driver = { +static struct spi_driver spi_max310x_uart_driver = { .driver = { .name = MAX310X_NAME, .owner = THIS_MODULE, @@ -1346,7 +1401,7 @@ static struct spi_driver max310x_uart_driver = { .remove = max310x_spi_remove, .id_table = max310x_id_table, }; -module_spi_driver(max310x_uart_driver); +module_spi_driver(spi_max310x_uart_driver); #endif MODULE_LICENSE("GPL"); -- 1.9.1 -- 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