[PATCH 1/3] max310x multi device

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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



[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux PPP]     [Linux FS]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Linmodem]     [Device Mapper]     [Linux Kernel for ARM]

  Powered by Linux