mirror of
https://github.com/torvalds/linux.git
synced 2024-12-02 09:01:34 +00:00
serial: sc16is7xx: hardware reset chip if reset-gpios is defined in DT
Some boards connect a GPIO to the reset pin, and the reset pin needs to be set up correctly before accessing the chip. Add a function to handle the chip reset. If the reset-gpios is defined in the DT, do hardware reset through this GPIO, otherwise do software reset as before. Reviewed-by: Lech Perczak <lech.perczak@camlingroup.com> Tested-by: Hugo Villeneuve <hvilleneuve@dimonoff.com> Reviewed-by: Hugo Villeneuve <hvilleneuve@dimonoff.com> Signed-off-by: Hui Wang <hui.wang@canonical.com> Link: https://lore.kernel.org/r/20240618112620.152848-2-hui.wang@canonical.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
a9411ef13f
commit
4fb92bdb8e
@ -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,29 @@ static const struct serial_rs485 sc16is7xx_rs485_supported = {
|
||||
.delay_rts_after_send = 1, /* Not supported but keep returning -EINVAL */
|
||||
};
|
||||
|
||||
/* Reset device, purging any pending irq / data */
|
||||
static int sc16is7xx_reset(struct device *dev, struct regmap *regmap)
|
||||
{
|
||||
struct gpio_desc *reset_gpio;
|
||||
|
||||
/* Assert reset GPIO if defined and valid. */
|
||||
reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(reset_gpio))
|
||||
return dev_err_probe(dev, PTR_ERR(reset_gpio), "Failed to get reset GPIO\n");
|
||||
|
||||
if (reset_gpio) {
|
||||
/* The minimum reset pulse width is 3 us. */
|
||||
fsleep(5);
|
||||
gpiod_set_value_cansleep(reset_gpio, 0); /* Deassert GPIO */
|
||||
} else {
|
||||
/* Software reset */
|
||||
regmap_write(regmap, SC16IS7XX_IOCONTROL_REG,
|
||||
SC16IS7XX_IOCONTROL_SRESET_BIT);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sc16is7xx_probe(struct device *dev, const struct sc16is7xx_devtype *devtype,
|
||||
struct regmap *regmaps[], int irq)
|
||||
{
|
||||
@ -1536,9 +1560,9 @@ 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);
|
||||
ret = sc16is7xx_reset(dev, regmaps[0]);
|
||||
if (ret)
|
||||
goto out_kthread;
|
||||
|
||||
/* Mark each port line and status as uninitialised. */
|
||||
for (i = 0; i < devtype->nr_uart; ++i) {
|
||||
@ -1663,6 +1687,7 @@ out_ports:
|
||||
uart_remove_one_port(&sc16is7xx_uart, &s->p[i].port);
|
||||
}
|
||||
|
||||
out_kthread:
|
||||
kthread_stop(s->kworker_task);
|
||||
|
||||
out_clk:
|
||||
|
Loading…
Reference in New Issue
Block a user