|
14 | 14 | #include <linux/delay.h>
|
15 | 15 | #include <linux/device.h>
|
16 | 16 | #include <linux/export.h>
|
| 17 | +#include <linux/gpio/consumer.h> |
17 | 18 | #include <linux/gpio/driver.h>
|
18 | 19 | #include <linux/idr.h>
|
19 | 20 | #include <linux/kthread.h>
|
@@ -1467,6 +1468,29 @@ static const struct serial_rs485 sc16is7xx_rs485_supported = {
|
1467 | 1468 | .delay_rts_after_send = 1, /* Not supported but keep returning -EINVAL */
|
1468 | 1469 | };
|
1469 | 1470 |
|
| 1471 | +/* Reset device, purging any pending irq / data */ |
| 1472 | +static int sc16is7xx_reset(struct device *dev, struct regmap *regmap) |
| 1473 | +{ |
| 1474 | + struct gpio_desc *reset_gpio; |
| 1475 | + |
| 1476 | + /* Assert reset GPIO if defined and valid. */ |
| 1477 | + reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); |
| 1478 | + if (IS_ERR(reset_gpio)) |
| 1479 | + return dev_err_probe(dev, PTR_ERR(reset_gpio), "Failed to get reset GPIO\n"); |
| 1480 | + |
| 1481 | + if (reset_gpio) { |
| 1482 | + /* The minimum reset pulse width is 3 us. */ |
| 1483 | + fsleep(5); |
| 1484 | + gpiod_set_value_cansleep(reset_gpio, 0); /* Deassert GPIO */ |
| 1485 | + } else { |
| 1486 | + /* Software reset */ |
| 1487 | + regmap_write(regmap, SC16IS7XX_IOCONTROL_REG, |
| 1488 | + SC16IS7XX_IOCONTROL_SRESET_BIT); |
| 1489 | + } |
| 1490 | + |
| 1491 | + return 0; |
| 1492 | +} |
| 1493 | + |
1470 | 1494 | int sc16is7xx_probe(struct device *dev, const struct sc16is7xx_devtype *devtype,
|
1471 | 1495 | struct regmap *regmaps[], int irq)
|
1472 | 1496 | {
|
@@ -1536,9 +1560,9 @@ int sc16is7xx_probe(struct device *dev, const struct sc16is7xx_devtype *devtype,
|
1536 | 1560 | }
|
1537 | 1561 | sched_set_fifo(s->kworker_task);
|
1538 | 1562 |
|
1539 |
| - /* reset device, purging any pending irq / data */ |
1540 |
| - regmap_write(regmaps[0], SC16IS7XX_IOCONTROL_REG, |
1541 |
| - SC16IS7XX_IOCONTROL_SRESET_BIT); |
| 1563 | + ret = sc16is7xx_reset(dev, regmaps[0]); |
| 1564 | + if (ret) |
| 1565 | + goto out_kthread; |
1542 | 1566 |
|
1543 | 1567 | /* Mark each port line and status as uninitialised. */
|
1544 | 1568 | for (i = 0; i < devtype->nr_uart; ++i) {
|
@@ -1663,6 +1687,7 @@ int sc16is7xx_probe(struct device *dev, const struct sc16is7xx_devtype *devtype,
|
1663 | 1687 | uart_remove_one_port(&sc16is7xx_uart, &s->p[i].port);
|
1664 | 1688 | }
|
1665 | 1689 |
|
| 1690 | +out_kthread: |
1666 | 1691 | kthread_stop(s->kworker_task);
|
1667 | 1692 |
|
1668 | 1693 | out_clk:
|
|
0 commit comments