|
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 |
@@ -52,19 +52,33 @@ static int ts4900_gpio_direction_input(struct gpio_chip *chip, |
52 | 52 | { |
53 | 53 | struct ts4900_gpio_priv *priv = gpiochip_get_data(chip); |
54 | 54 |
|
55 | | - /* |
56 | | - * This will clear the output enable bit, the other bits are |
57 | | - * dontcare when this is cleared |
| 55 | + /* Only clear the OE bit here, requires a RMW. Prevents potential issue |
| 56 | + * with OE and data getting to the physical pin at different times. |
58 | 57 | */ |
59 | | - return regmap_write(priv->regmap, offset, 0); |
| 58 | + return regmap_update_bits(priv->regmap, offset, TS4900_GPIO_OE, 0); |
60 | 59 | } |
61 | 60 |
|
62 | 61 | static int ts4900_gpio_direction_output(struct gpio_chip *chip, |
63 | 62 | unsigned int offset, int value) |
64 | 63 | { |
65 | 64 | struct ts4900_gpio_priv *priv = gpiochip_get_data(chip); |
| 65 | + unsigned int reg; |
66 | 66 | int ret; |
67 | 67 |
|
| 68 | + /* If changing from an input to an output, we need to first set the |
| 69 | + * proper data bit to what is requested and then set OE bit. This |
| 70 | + * prevents a glitch that can occur on the IO line |
| 71 | + */ |
| 72 | + regmap_read(priv->regmap, offset, ®); |
| 73 | + if (!(reg & TS4900_GPIO_OE)) { |
| 74 | + if (value) |
| 75 | + reg = TS4900_GPIO_OUT; |
| 76 | + else |
| 77 | + reg &= ~TS4900_GPIO_OUT; |
| 78 | + |
| 79 | + regmap_write(priv->regmap, offset, reg); |
| 80 | + } |
| 81 | + |
68 | 82 | if (value) |
69 | 83 | ret = regmap_write(priv->regmap, offset, TS4900_GPIO_OE | |
70 | 84 | TS4900_GPIO_OUT); |
|
0 commit comments