Commit e6540f332447b2fe5c2cd8774890c80f29fe5c75

Authored by Vincent Donnefort
Committed by Lee Jones
1 parent bb62a35bd5

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