On Tue, 4 Jun 2024 21:27:26 +0800 Hui Wang <hui.wang@xxxxxxxxxxxxx> wrote: Hi Hui, > Certain designs connect a gpio to the reset pin, and the reset pin > needs to be setup correctly before accessing the chip. > > Here adding a function to handle the chip reset. If the reset-gpios is > defined in the dt, do the hard reset through this gpio, othwerwise do > the soft reset as before. > > Reviewed-by: Hugo Villeneuve <hvilleneuve@xxxxxxxxxxxx> I never gave you permission to add this tag, remove it. Make sure you fully understand the meaning of tags by reading patches submission guidelines. > Signed-off-by: Hui Wang <hui.wang@xxxxxxxxxxxxx> > --- > In the v2: > - move the soft reset and hard reset into one fucntion > - move the reset function to sc16is7xx.c and call it in _probe() > - add udelay(5) before deasserting the gpio reset pin > > drivers/tty/serial/sc16is7xx.c | 28 ++++++++++++++++++++++++---- > 1 file changed, 24 insertions(+), 4 deletions(-) > > diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c > index bf0065d1c8e9..119abfb4607c 100644 > --- a/drivers/tty/serial/sc16is7xx.c > +++ b/drivers/tty/serial/sc16is7xx.c > @@ -14,6 +14,7 @@ > #include <linux/delay.h> > #include <linux/device.h> > #include <linux/export.h> > +#include <linux/gpio/consumer.h> > #include <linux/gpio/driver.h> > #include <linux/idr.h> > #include <linux/kthread.h> > @@ -1467,6 +1468,25 @@ static const struct serial_rs485 sc16is7xx_rs485_supported = { > .delay_rts_after_send = 1, /* Not supported but keep returning -EINVAL */ > }; > Add function description from original comment "Reset device, purging any pending irq / data", since the comment applies to both hardware and software reset, > +static int sc16is7xx_reset(struct device *dev, struct regmap *regmaps[]) Simply pass "struct regmap *regmap" as the second argument. See sc16is7xx_setup_mctrl_ports() for example. > +{ > + struct gpio_desc *reset_gpiod; reset_gpiod -> reset_gpio > + > + reset_gpiod = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); > + if (!reset_gpiod) Follow Andy's suggestion here. > + /* soft reset device, purging any pending irq / data */ "Software reset". > + regmap_write(regmaps[0], SC16IS7XX_IOCONTROL_REG, > + SC16IS7XX_IOCONTROL_SRESET_BIT); > + else if (!IS_ERR(reset_gpiod)) { > + /* delay 5 us (at least 3 us) and deassert the gpio to exit the hard reset */ You can omit the "delay 5 us" since it is obvious from the code. Maybe add that "The minimum reset pulse width is 3 us" as stated in the datasheet. As a general note for your comments: capitalize the first letter, ex: "Deassert GPIO" and not "deassert GPIO". > + udelay(5); > + gpiod_set_value_cansleep(reset_gpiod, 0); Move the comment "deassert the gpio to exit the hard reset" here. You could also simplify it as "Deassert GPIO.". > + } else > + return PTR_ERR(reset_gpiod); return dev_err_probe(dev, PTR_ERR(reset_gpiod), "Failed to get reset GPIO\n"); > + > + return 0; > +} > + > int sc16is7xx_probe(struct device *dev, const struct sc16is7xx_devtype *devtype, > struct regmap *regmaps[], int irq) > { > @@ -1527,6 +1547,10 @@ int sc16is7xx_probe(struct device *dev, const struct sc16is7xx_devtype *devtype, > s->devtype = devtype; > dev_set_drvdata(dev, s); > > + ret = sc16is7xx_reset(dev, regmaps); > + if (ret) > + goto out_clk; > + > kthread_init_worker(&s->kworker); > s->kworker_task = kthread_run(kthread_worker_fn, &s->kworker, > "sc16is7xx"); > @@ -1536,10 +1560,6 @@ int sc16is7xx_probe(struct device *dev, const struct sc16is7xx_devtype *devtype, > } > sched_set_fifo(s->kworker_task); > > - /* reset device, purging any pending irq / data */ > - regmap_write(regmaps[0], SC16IS7XX_IOCONTROL_REG, > - SC16IS7XX_IOCONTROL_SRESET_BIT); > - > /* Mark each port line and status as uninitialised. */ > for (i = 0; i < devtype->nr_uart; ++i) { > s->p[i].port.line = SC16IS7XX_MAX_DEVS; > -- > 2.34.1 > > > -- Hugo Villeneuve