Re: Driver Max310x called more than once

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

 



Thank you Alexander for taking time,



Well I'm not an expert, so correct me If I'm wrong: but if I'm using
the clock node with fixed-clock property, therefore this function will
be called :
ret = clk_prepare_enable(s->clk)

That the part that I don't like, or I don't need. I don't want the
processor to create a clock and use ressources for an unused clock.
The clock node is good when you want your processor to generate the
clock, but in my case, I don't need it.




"Are you sure max310xs[k] will be NULL after remove driver?"



I will work on it.


I was inspired by this :
http://lxr.free-electrons.com/source/drivers/tty/serial/max3100.c?v=4.1
, but yes module_init will be better.




Do you know how can I create one patch that look at the difference
between the master branch and 4 commit behind ?


Micka,







Le jeu. 7 avr. 2016 à 21:54, Alexander Shiyan <shc_work@xxxxxxx> a écrit :
>
> On Thu, 7 Apr 2016 15:44:35 +0200
> Micka <mickamusset@xxxxxxxxx> wrote:
>
> Hello.
>
> > 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 still can not understand why use a separate property to specify the frequency
> Why you can not use "fixed-clock" node and just specify the type "osc" or "xtal"?
>
> > I added the property no-gpio in case u don't want to use the gpio on
> > the max310x.
>
> You can re-use existing property "gpio-controller" for this, like as:
>   if (!of_find_property(np, "gpio-controller", NULL))
>   ...
>
> > 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.
>
> This is a work for SPI core.
>
> ...
> > 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
> ...
> >  struct max310x_port {
> > - struct uart_driver uart;
> > + int nr;
> > + int index;
> > +// struct uart_driver uart;
>
> Linux style for comments is the C89 "/* ... */" style.
>
> ...
> >  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);
>
> ???
>
> ...
> > @@ -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;
>
> Are you sure max310xs[k] will be NULL after remove driver?
>
> > + // 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;
> > +        }
>
> Hmm... I think moving uart_register_driver in the "module_init" initcall
> will be more elegant, like:
> static int __init max310x_init(void)
> {
>         ret = uart_register_driver(&max310x_uart_driver);
>         if (!ret) {
>                 ret = spi_register_driver(&max310x_spi_driver);
>                 ...
>         }
>
>         return ret;
> }
> module_init(max310x_init);
>
> ...
> > - 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;
>
> In any case please make clock & gpio changes as a separate part of patch.
>
> ...
> > @@ -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);
>
> for(j=0;(j<5... Not a good idea.
> If you want to make an infinite loop protect, let's use time_is_after_jiffies().
>
> ...
>
> Thanks.
>
> --
> Alexander Shiyan <shc_work@xxxxxxx>
--
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