Commit f8323b6b authored by Mika Westerberg's avatar Mika Westerberg Committed by Linus Walleij

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: default avatarBenjamin Adler <benadler@gmx.net>
Signed-off-by: default avatarMika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent 40eeb111
...@@ -158,40 +158,49 @@ static void __iomem *byt_gpio_reg(struct gpio_chip *chip, unsigned offset, ...@@ -158,40 +158,49 @@ static void __iomem *byt_gpio_reg(struct gpio_chip *chip, unsigned offset,
return vg->reg_base + reg_offset + reg; return vg->reg_base + reg_offset + reg;
} }
static bool is_special_pin(struct byt_gpio *vg, unsigned offset) static u32 byt_get_gpio_mux(struct byt_gpio *vg, unsigned offset)
{ {
/* SCORE pin 92-93 */ /* SCORE pin 92-93 */
if (!strcmp(vg->range->name, BYT_SCORE_ACPI_UID) && if (!strcmp(vg->range->name, BYT_SCORE_ACPI_UID) &&
offset >= 92 && offset <= 93) offset >= 92 && offset <= 93)
return true; return 1;
/* SUS pin 11-21 */ /* SUS pin 11-21 */
if (!strcmp(vg->range->name, BYT_SUS_ACPI_UID) && if (!strcmp(vg->range->name, BYT_SUS_ACPI_UID) &&
offset >= 11 && offset <= 21) offset >= 11 && offset <= 21)
return true; return 1;
return false; return 0;
} }
static int byt_gpio_request(struct gpio_chip *chip, unsigned offset) static int byt_gpio_request(struct gpio_chip *chip, unsigned offset)
{ {
struct byt_gpio *vg = to_byt_gpio(chip); struct byt_gpio *vg = to_byt_gpio(chip);
void __iomem *reg = byt_gpio_reg(chip, offset, BYT_CONF0_REG); void __iomem *reg = byt_gpio_reg(chip, offset, BYT_CONF0_REG);
u32 value; u32 value, gpio_mux;
bool special;
/* /*
* In most cases, func pin mux 000 means GPIO function. * In most cases, func pin mux 000 means GPIO function.
* But, some pins may have func pin mux 001 represents * But, some pins may have func pin mux 001 represents
* GPIO function. Only allow user to export pin with * GPIO function.
* func pin mux preset as GPIO function by BIOS/FW. *
* Because there are devices out there where some pins were not
* configured correctly we allow changing the mux value from
* request (but print out warning about that).
*/ */
value = readl(reg) & BYT_PIN_MUX; value = readl(reg) & BYT_PIN_MUX;
special = is_special_pin(vg, offset); gpio_mux = byt_get_gpio_mux(vg, offset);
if ((special && value != 1) || (!special && value)) { if (WARN_ON(gpio_mux != value)) {
dev_err(&vg->pdev->dev, unsigned long flags;
"pin %u cannot be used as GPIO.\n", offset);
return -EINVAL; spin_lock_irqsave(&vg->lock, flags);
value = readl(reg) & ~BYT_PIN_MUX;
value |= gpio_mux;
writel(value, reg);
spin_unlock_irqrestore(&vg->lock, flags);
dev_warn(&vg->pdev->dev,
"pin %u forcibly re-configured as GPIO\n", offset);
} }
pm_runtime_get(&vg->pdev->dev); pm_runtime_get(&vg->pdev->dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment