Re: Driver Max310x called more than once

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

 



I can't config the mail server .... on git, I don't have any mail
server .... i'm using gmail.

I prefer to keep the property clock-frequency: Because that way i
don't need a node clock and I don't need to initialize a clock in the
processor ( ret = clk_prepare_enable(s->clk)  ).
I added the property no-gpio in case u don't want to use the gpio on
the max310x.

Now, I'm concerned about two max310x working at the same time. What
will happen ? There is no mutex to protect that in the driver. I hope
that the spi driver will handle that problem. What do you think
Alexander.

You will find there the patch :


diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
index 182549f..328bbe0 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,23 @@ 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 int uart_driver_registered;   /* flag to indicate if the
driver is registered*/
+static int number_of_uarts;   /* numbe of uarts*/
+
 static u8 max310x_port_read(struct uart_port *port, u8 reg)
 {
  struct max310x_port *s = dev_get_drvdata(port->dev);
  unsigned int val = 0;
-
  regmap_read(s->regmap, port->iobase + reg, &val);

  return val;
@@ -289,14 +305,12 @@ 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);
-
  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);
-
  regmap_update_bits(s->regmap, port->iobase + reg, mask, val);
 }

@@ -715,13 +729,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 +759,7 @@ 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);
  if (!work_pending(&one->tx_work))
  schedule_work(&one->tx_work);
 }
@@ -753,7 +767,7 @@ 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);
  lvl = max310x_port_read(port, MAX310X_TXFIFOLVL_REG);
  sts = max310x_port_read(port, MAX310X_IRQSTS_REG);

@@ -914,7 +928,6 @@ static int max310x_startup(struct uart_port *port)
 {
  struct max310x_port *s = dev_get_drvdata(port->dev);
  unsigned int val;
-
  s->devtype->power(port, 1);

  /* Configure MODE1 register */
@@ -1009,8 +1022,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 +1035,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,46 +1094,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);
+ // did we registered the driver ?
+ if (!uart_driver_registered) {
+ // no, let's do it :
+ // set the flag to 1 for the next time.
+                 uart_driver_registered = 1;
+ // register the driver :
+                 retval = uart_register_driver(&max310x_uart_driver);
+                 if (retval) {
+ // something goes wrong :
+                         return retval;
+                 }
+ number_of_uarts=0;
+ }
+ // find a free spot in the array :
+        for (k = 0; k < MAX_MAX310X; k++)
+                 if (!max310xs[k])
+                         break;
+ // test if we reach the end of the array
+        if (k == MAX_MAX310X) {
+ // no more space available
+                dev_warn(dev, "too many MAX310X chips\n");
+                 return -ENOMEM;
+        }
+

  /* 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);
+
+
  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;
+ // save the index of the array
+ s->index=k;
+ // test if we can get the frequency of the clock from the property :
+ if (of_find_property(dev->of_node, "clock-frequency", NULL)){
+ // cool, let's get it :
+ of_property_read_u32(dev->of_node, "clock-frequency", &freq);
+        }
+ // check if the frequency is indicated :
+        if(freq!=0){
+ // yes ! we don't need to build a clock in the processor :
+               fmin = 1000000;
+               fmax = 4000000;
+               xtal = 0;
+        }else{
+ // we need an internal clock
+ 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) {
  ret = -ERANGE;
@@ -1133,23 +1187,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){
  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);
+ }
+ // did the port start ? if not, restart the process ... maybe we
need to stop at some point the wait ....
+ }while(ret!=0x01);

  regmap_update_bits(s->regmap, MAX310X_MODE1_REG + offs,
    MAX310X_MODE1_AUTOSLEEP_BIT,
@@ -1157,42 +1215,34 @@ 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;
- }
+ s->nr = devtype->nr;

+ // check if we should add gpio support to this max310x:
 #ifdef CONFIG_GPIOLIB
- /* Setup GPIO cotroller */
- s->gpio.owner = THIS_MODULE;
- s->gpio.dev = dev;
- s->gpio.label = dev_name(dev);
- s->gpio.direction_input = max310x_gpio_direction_input;
- s->gpio.get = max310x_gpio_get;
- s->gpio.direction_output= max310x_gpio_direction_output;
- s->gpio.set = max310x_gpio_set;
- s->gpio.base = -1;
- s->gpio.ngpio = devtype->nr * 4;
- s->gpio.can_sleep = 1;
- ret = gpiochip_add(&s->gpio);
- if (ret)
- goto out_uart;
+ if (!of_find_property(dev->of_node, "no-gpio", NULL)){
+ /* Setup GPIO cotroller */
+ s->gpio.owner = THIS_MODULE;
+ s->gpio.dev = dev;
+ s->gpio.label = dev_name(dev);
+ s->gpio.direction_input = max310x_gpio_direction_input;
+ s->gpio.get = max310x_gpio_get;
+ s->gpio.direction_output= max310x_gpio_direction_output;
+ s->gpio.set = max310x_gpio_set;
+ s->gpio.base = -1;
+ s->gpio.ngpio = devtype->nr * 4;
+ s->gpio.can_sleep = 1;
+ ret = gpiochip_add(&s->gpio);
+ if (ret){
+ goto out_uart;
+ }
+ }
 #endif
-
+ // init the mutex:
  mutex_init(&s->mutex);
-
  for (i = 0; i < devtype->nr; i++) {
  /* Initialize port data */
- s->p[i].port.line = i;
+ //
+ s->p[i].port.line = number_of_uarts++; // get a unique ID
  s->p[i].port.dev = dev;
  s->p[i].port.irq = irq;
  s->p[i].port.type = PORT_MAX310X;
@@ -1217,7 +1267,7 @@ 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);
+ uart_add_one_port( &max310x_uart_driver, &s->p[i].port);
  /* Go to suspend mode */
  devtype->power(&s->p[i].port, 0);
  }
@@ -1225,9 +1275,9 @@ 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){
  return 0;
-
+ }
  dev_err(dev, "Unable to reguest IRQ %i\n", irq);

  mutex_destroy(&s->mutex);
@@ -1237,7 +1287,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 +1304,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 +1385,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 +1396,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");

On Thu, Apr 7, 2016 at 1:14 PM, Alexander Shiyan <shc_work@xxxxxxx> wrote:
>> Четверг,  7 апреля 2016, 13:35 +03:00 от Micka <mickamusset@xxxxxxxxx>:
>
>> Hi,
>>
>> You will find a new diff without printk
> ...
>
> Hello.
>
> Please use "git send-email" for the patches.
>
> "clock-frequency" property is excessive, frequency can be taken from the clock node.
>
> Is probe/remove functions needs to use locks? Afaik these calls is serialized, fix me please.
>
> Thanks.
>
> ---
>
--
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