aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpio-ich.c
diff options
context:
space:
mode:
authorVincent Donnefort <vdonnefort@gmail.com>2014-02-14 09:01:57 -0500
committerLee Jones <lee.jones@linaro.org>2014-03-19 04:58:23 -0400
commite6540f332447b2fe5c2cd8774890c80f29fe5c75 (patch)
treeae8e433ce321c553a452a38e9e68e1b939a574b1 /drivers/gpio/gpio-ich.c
parentbb62a35bd5d96e506af0ea8dd145480b9172a2a6 (diff)
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>
Diffstat (limited to 'drivers/gpio/gpio-ich.c')
-rw-r--r--drivers/gpio/gpio-ich.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/drivers/gpio/gpio-ich.c b/drivers/gpio/gpio-ich.c
index f3eb1c52f97b..bfef20f8ab48 100644
--- a/drivers/gpio/gpio-ich.c
+++ b/drivers/gpio/gpio-ich.c
@@ -78,6 +78,12 @@ struct ichx_desc {
78 /* Some chipsets have quirks, let these use their own request/get */ 78 /* Some chipsets have quirks, let these use their own request/get */
79 int (*request)(struct gpio_chip *chip, unsigned offset); 79 int (*request)(struct gpio_chip *chip, unsigned offset);
80 int (*get)(struct gpio_chip *chip, unsigned offset); 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
83static struct { 89static struct {
@@ -89,6 +95,7 @@ static struct {
89 struct ichx_desc *desc; /* Pointer to chipset-specific description */ 95 struct ichx_desc *desc; /* Pointer to chipset-specific description */
90 u32 orig_gpio_ctrl; /* Orig CTRL value, used to restore on exit */ 96 u32 orig_gpio_ctrl; /* Orig CTRL value, used to restore on exit */
91 u8 use_gpio; /* Which GPIO groups are usable */ 97 u8 use_gpio; /* Which GPIO groups are usable */
98 int outlvl_cache[3]; /* cached output values */
92} ichx_priv; 99} ichx_priv;
93 100
94static int modparam_gpiobase = -1; /* dynamic */ 101static int modparam_gpiobase = -1; /* dynamic */
@@ -106,14 +113,21 @@ static int ichx_write_bit(int reg, unsigned nr, int val, int verify)
106 113
107 spin_lock_irqsave(&ichx_priv.lock, flags); 114 spin_lock_irqsave(&ichx_priv.lock, flags);
108 115
109 data = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr], 116 if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache)
110 ichx_priv.gpio_base); 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 if (val) 122 if (val)
112 data |= 1 << bit; 123 data |= 1 << bit;
113 else 124 else
114 data &= ~(1 << bit); 125 data &= ~(1 << bit);
115 ICHX_WRITE(data, ichx_priv.desc->regs[reg][reg_nr], 126 ICHX_WRITE(data, ichx_priv.desc->regs[reg][reg_nr],
116 ichx_priv.gpio_base); 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 tmp = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr], 131 tmp = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr],
118 ichx_priv.gpio_base); 132 ichx_priv.gpio_base);
119 if (verify && data != tmp) 133 if (verify && data != tmp)
@@ -136,6 +150,9 @@ static int ichx_read_bit(int reg, unsigned nr)
136 data = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr], 150 data = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr],
137 ichx_priv.gpio_base); 151 ichx_priv.gpio_base);
138 152
153 if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache)
154 data = ichx_priv.outlvl_cache[reg_nr] | data;
155
139 spin_unlock_irqrestore(&ichx_priv.lock, flags); 156 spin_unlock_irqrestore(&ichx_priv.lock, flags);
140 157
141 return data & (1 << bit) ? 1 : 0; 158 return data & (1 << bit) ? 1 : 0;