Commit e6540f332447b2fe5c2cd8774890c80f29fe5c75
Committed by
Lee Jones
1 parent
bb62a35bd5
Exists in
master
and in
13 other branches
gpio: ich: Add output levels cache support
This patch allows GPIO driver to cache GPIO_LVL output registers. The aim is to support chipsets on which GPIO_LVL value can't be read for output pins. Caching output levels implies the first output values reading as 0. The driver so can't be aware of set values GPIOs by bootloader or BIOS. Acked-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Vincent Donnefort <vdonnefort@gmail.com> Signed-off-by: Lee Jones <lee.jones@linaro.org>
Showing 1 changed file with 19 additions and 2 deletions Side-by-side Diff
drivers/gpio/gpio-ich.c
... | ... | @@ -78,6 +78,12 @@ |
78 | 78 | /* Some chipsets have quirks, let these use their own request/get */ |
79 | 79 | int (*request)(struct gpio_chip *chip, unsigned offset); |
80 | 80 | int (*get)(struct gpio_chip *chip, unsigned offset); |
81 | + | |
82 | + /* | |
83 | + * Some chipsets don't let reading output values on GPIO_LVL register | |
84 | + * this option allows driver caching written output values | |
85 | + */ | |
86 | + bool use_outlvl_cache; | |
81 | 87 | }; |
82 | 88 | |
83 | 89 | static struct { |
... | ... | @@ -89,6 +95,7 @@ |
89 | 95 | struct ichx_desc *desc; /* Pointer to chipset-specific description */ |
90 | 96 | u32 orig_gpio_ctrl; /* Orig CTRL value, used to restore on exit */ |
91 | 97 | u8 use_gpio; /* Which GPIO groups are usable */ |
98 | + int outlvl_cache[3]; /* cached output values */ | |
92 | 99 | } ichx_priv; |
93 | 100 | |
94 | 101 | static int modparam_gpiobase = -1; /* dynamic */ |
95 | 102 | |
... | ... | @@ -106,14 +113,21 @@ |
106 | 113 | |
107 | 114 | spin_lock_irqsave(&ichx_priv.lock, flags); |
108 | 115 | |
109 | - data = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr], | |
110 | - ichx_priv.gpio_base); | |
116 | + if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache) | |
117 | + data = ichx_priv.outlvl_cache[reg_nr]; | |
118 | + else | |
119 | + data = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr], | |
120 | + ichx_priv.gpio_base); | |
121 | + | |
111 | 122 | if (val) |
112 | 123 | data |= 1 << bit; |
113 | 124 | else |
114 | 125 | data &= ~(1 << bit); |
115 | 126 | ICHX_WRITE(data, ichx_priv.desc->regs[reg][reg_nr], |
116 | 127 | ichx_priv.gpio_base); |
128 | + if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache) | |
129 | + ichx_priv.outlvl_cache[reg_nr] = data; | |
130 | + | |
117 | 131 | tmp = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr], |
118 | 132 | ichx_priv.gpio_base); |
119 | 133 | if (verify && data != tmp) |
... | ... | @@ -135,6 +149,9 @@ |
135 | 149 | |
136 | 150 | data = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr], |
137 | 151 | ichx_priv.gpio_base); |
152 | + | |
153 | + if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache) | |
154 | + data = ichx_priv.outlvl_cache[reg_nr] | data; | |
138 | 155 | |
139 | 156 | spin_unlock_irqrestore(&ichx_priv.lock, flags); |
140 | 157 |