|
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