|
1 | 1 | /*
|
2 | 2 | * Digital I/O driver for Technologic Systems I2C FPGA Core
|
3 | 3 | *
|
4 |
| - * Copyright (C) 2015 Technologic Systems |
| 4 | + * Copyright (C) 2015, 2018 Technologic Systems |
5 | 5 | * Copyright (C) 2016 Savoir-Faire Linux
|
6 | 6 | *
|
7 | 7 | * This program is free software; you can redistribute it and/or
|
@@ -55,19 +55,33 @@ static int ts4900_gpio_direction_input(struct gpio_chip *chip,
|
55 | 55 | {
|
56 | 56 | struct ts4900_gpio_priv *priv = gpiochip_get_data(chip);
|
57 | 57 |
|
58 |
| - /* |
59 |
| - * This will clear the output enable bit, the other bits are |
60 |
| - * dontcare when this is cleared |
| 58 | + /* Only clear the OE bit here, requires a RMW. Prevents potential issue |
| 59 | + * with OE and data getting to the physical pin at different times. |
61 | 60 | */
|
62 |
| - return regmap_write(priv->regmap, offset, 0); |
| 61 | + return regmap_update_bits(priv->regmap, offset, TS4900_GPIO_OE, 0); |
63 | 62 | }
|
64 | 63 |
|
65 | 64 | static int ts4900_gpio_direction_output(struct gpio_chip *chip,
|
66 | 65 | unsigned int offset, int value)
|
67 | 66 | {
|
68 | 67 | struct ts4900_gpio_priv *priv = gpiochip_get_data(chip);
|
| 68 | + unsigned int reg; |
69 | 69 | int ret;
|
70 | 70 |
|
| 71 | + /* If changing from an input to an output, we need to first set the |
| 72 | + * proper data bit to what is requested and then set OE bit. This |
| 73 | + * prevents a glitch that can occur on the IO line |
| 74 | + */ |
| 75 | + regmap_read(priv->regmap, offset, ®); |
| 76 | + if (!(reg & TS4900_GPIO_OE)) { |
| 77 | + if (value) |
| 78 | + reg = TS4900_GPIO_OUT; |
| 79 | + else |
| 80 | + reg &= ~TS4900_GPIO_OUT; |
| 81 | + |
| 82 | + regmap_write(priv->regmap, offset, reg); |
| 83 | + } |
| 84 | + |
71 | 85 | if (value)
|
72 | 86 | ret = regmap_write(priv->regmap, offset, TS4900_GPIO_OE |
|
73 | 87 | TS4900_GPIO_OUT);
|
|
0 commit comments