aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@linux.intel.com>2015-02-23 07:53:10 -0500
committerLinus Walleij <linus.walleij@linaro.org>2015-03-06 06:19:51 -0500
commitf8323b6bb2cc7d26941d4838dd4375952980a88a (patch)
treea1fd712b834c97c7c37c1f7680c4f411565a09e8
parent40eeb111d7c88bfbc38e1dfe330bc4cec05e0806 (diff)
pinctrl: baytrail: Relax GPIO request rules
Zotac ZBOX PI320, a Baytrail based mini-PC, has power button connected to a GPIO pin and it is exposed to the operating system as Windows 8 button array. This is implemented in Linux as a driver using gpio_keys. However, BIOS on this particula machine forgot to mux the pin to be a GPIO instead of native function, which results following message to be seen on the console: byt_gpio INT33FC:02: pin 16 cannot be used as GPIO. This causes power button to not work as the driver was not able to request the GPIO it needs. So instead of completely preventing this we allow turning the pin as GPIO but issue warning that something might be wrong. Reported-by: Benjamin Adler <benadler@gmx.net> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r--drivers/pinctrl/intel/pinctrl-baytrail.c35
1 files changed, 22 insertions, 13 deletions
diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c
index 5afe03e28b91..e44f2fd6753f 100644
--- a/drivers/pinctrl/intel/pinctrl-baytrail.c
+++ b/drivers/pinctrl/intel/pinctrl-baytrail.c
@@ -158,40 +158,49 @@ static void __iomem *byt_gpio_reg(struct gpio_chip *chip, unsigned offset,
158 return vg->reg_base + reg_offset + reg; 158 return vg->reg_base + reg_offset + reg;
159} 159}
160 160
161static bool is_special_pin(struct byt_gpio *vg, unsigned offset) 161static u32 byt_get_gpio_mux(struct byt_gpio *vg, unsigned offset)
162{ 162{
163 /* SCORE pin 92-93 */ 163 /* SCORE pin 92-93 */
164 if (!strcmp(vg->range->name, BYT_SCORE_ACPI_UID) && 164 if (!strcmp(vg->range->name, BYT_SCORE_ACPI_UID) &&
165 offset >= 92 && offset <= 93) 165 offset >= 92 && offset <= 93)
166 return true; 166 return 1;
167 167
168 /* SUS pin 11-21 */ 168 /* SUS pin 11-21 */
169 if (!strcmp(vg->range->name, BYT_SUS_ACPI_UID) && 169 if (!strcmp(vg->range->name, BYT_SUS_ACPI_UID) &&
170 offset >= 11 && offset <= 21) 170 offset >= 11 && offset <= 21)
171 return true; 171 return 1;
172 172
173 return false; 173 return 0;
174} 174}
175 175
176static int byt_gpio_request(struct gpio_chip *chip, unsigned offset) 176static int byt_gpio_request(struct gpio_chip *chip, unsigned offset)
177{ 177{
178 struct byt_gpio *vg = to_byt_gpio(chip); 178 struct byt_gpio *vg = to_byt_gpio(chip);
179 void __iomem *reg = byt_gpio_reg(chip, offset, BYT_CONF0_REG); 179 void __iomem *reg = byt_gpio_reg(chip, offset, BYT_CONF0_REG);
180 u32 value; 180 u32 value, gpio_mux;
181 bool special;
182 181
183 /* 182 /*
184 * In most cases, func pin mux 000 means GPIO function. 183 * In most cases, func pin mux 000 means GPIO function.
185 * But, some pins may have func pin mux 001 represents 184 * But, some pins may have func pin mux 001 represents
186 * GPIO function. Only allow user to export pin with 185 * GPIO function.
187 * func pin mux preset as GPIO function by BIOS/FW. 186 *
187 * Because there are devices out there where some pins were not
188 * configured correctly we allow changing the mux value from
189 * request (but print out warning about that).
188 */ 190 */
189 value = readl(reg) & BYT_PIN_MUX; 191 value = readl(reg) & BYT_PIN_MUX;
190 special = is_special_pin(vg, offset); 192 gpio_mux = byt_get_gpio_mux(vg, offset);
191 if ((special && value != 1) || (!special && value)) { 193 if (WARN_ON(gpio_mux != value)) {
192 dev_err(&vg->pdev->dev, 194 unsigned long flags;
193 "pin %u cannot be used as GPIO.\n", offset); 195
194 return -EINVAL; 196 spin_lock_irqsave(&vg->lock, flags);
197 value = readl(reg) & ~BYT_PIN_MUX;
198 value |= gpio_mux;
199 writel(value, reg);
200 spin_unlock_irqrestore(&vg->lock, flags);
201
202 dev_warn(&vg->pdev->dev,
203 "pin %u forcibly re-configured as GPIO\n", offset);
195 } 204 }
196 205
197 pm_runtime_get(&vg->pdev->dev); 206 pm_runtime_get(&vg->pdev->dev);