stable.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Patch "gpio: crystalcove: Do not write regular gpio registers for virtual GPIOs" has been added to the 4.9-stable tree
@ 2018-04-09 19:58 gregkh
  0 siblings, 0 replies; only message in thread
From: gregkh @ 2018-04-09 19:58 UTC (permalink / raw)
  To: hdegoede, aaron.lu, alexander.levin, andriy.shevchenko, gregkh,
	linus.walleij
  Cc: stable, stable-commits


This is a note to let you know that I've just added the patch titled

    gpio: crystalcove: Do not write regular gpio registers for virtual GPIOs

to the 4.9-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     gpio-crystalcove-do-not-write-regular-gpio-registers-for-virtual-gpios.patch
and it can be found in the queue-4.9 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@vger.kernel.org> know about it.


>From foo@baz Mon Apr  9 17:09:24 CEST 2018
From: Hans de Goede <hdegoede@redhat.com>
Date: Sat, 13 May 2017 14:39:53 +0200
Subject: gpio: crystalcove: Do not write regular gpio registers for virtual GPIOs

From: Hans de Goede <hdegoede@redhat.com>


[ Upstream commit 9a752b4c9ab924033bfdb8784c680d50b2bd5684 ]

The Crystal Cove PMIC has 16 real GPIOs but the ACPI code for devices
with this PMIC may address up to 95 GPIOs, these extra GPIOs are
called virtual GPIOs and are used by the ACPI code as a method of
accessing various non GPIO bits of PMIC.

Commit dcdc3018d635 ("gpio: crystalcove: support virtual GPIO") added
dummy support for these to avoid a bunch of ACPI errors, but instead of
ignoring writes / reads to them by doing:

if (gpio >= CRYSTALCOVE_GPIO_NUM)
	return 0;

It accidentally introduced the following wrong check:

if (gpio > CRYSTALCOVE_VGPIO_NUM)
	return 0;

Which means that attempts by the ACPI code to access these gpios
causes some arbitrary gpio to get touched through for example
GPIO1P0CTLO + gpionr % 8.

Since we do support input/output (but not interrupts) on the 0x5e
virtual GPIO, this commit makes to_reg return -ENOTSUPP for unsupported
virtual GPIOs so as to not have to check for (gpio >= CRYSTALCOVE_GPIO_NUM
&& gpio != 0x5e) everywhere and to make it easier to add support for more
virtual GPIOs in the future.

It then adds a check for to_reg returning an error to all callers where
this may happen fixing the ACPI code accessing virtual GPIOs accidentally
causing changes to real GPIOs.

Fixes: dcdc3018d635 ("gpio: crystalcove: support virtual GPIO")
Cc: Aaron Lu <aaron.lu@intel.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/gpio/gpio-crystalcove.c |   54 ++++++++++++++++++++++++++--------------
 1 file changed, 36 insertions(+), 18 deletions(-)

--- a/drivers/gpio/gpio-crystalcove.c
+++ b/drivers/gpio/gpio-crystalcove.c
@@ -90,8 +90,18 @@ static inline int to_reg(int gpio, enum
 {
 	int reg;
 
-	if (gpio == 94)
-		return GPIOPANELCTL;
+	if (gpio >= CRYSTALCOVE_GPIO_NUM) {
+		/*
+		 * Virtual GPIO called from ACPI, for now we only support
+		 * the panel ctl.
+		 */
+		switch (gpio) {
+		case 0x5e:
+			return GPIOPANELCTL;
+		default:
+			return -EOPNOTSUPP;
+		}
+	}
 
 	if (reg_type == CTRL_IN) {
 		if (gpio < 8)
@@ -130,36 +140,36 @@ static void crystalcove_update_irq_ctrl(
 static int crystalcove_gpio_dir_in(struct gpio_chip *chip, unsigned gpio)
 {
 	struct crystalcove_gpio *cg = gpiochip_get_data(chip);
+	int reg = to_reg(gpio, CTRL_OUT);
 
-	if (gpio > CRYSTALCOVE_VGPIO_NUM)
+	if (reg < 0)
 		return 0;
 
-	return regmap_write(cg->regmap, to_reg(gpio, CTRL_OUT),
-			    CTLO_INPUT_SET);
+	return regmap_write(cg->regmap, reg, CTLO_INPUT_SET);
 }
 
 static int crystalcove_gpio_dir_out(struct gpio_chip *chip, unsigned gpio,
 				    int value)
 {
 	struct crystalcove_gpio *cg = gpiochip_get_data(chip);
+	int reg = to_reg(gpio, CTRL_OUT);
 
-	if (gpio > CRYSTALCOVE_VGPIO_NUM)
+	if (reg < 0)
 		return 0;
 
-	return regmap_write(cg->regmap, to_reg(gpio, CTRL_OUT),
-			    CTLO_OUTPUT_SET | value);
+	return regmap_write(cg->regmap, reg, CTLO_OUTPUT_SET | value);
 }
 
 static int crystalcove_gpio_get(struct gpio_chip *chip, unsigned gpio)
 {
 	struct crystalcove_gpio *cg = gpiochip_get_data(chip);
-	int ret;
 	unsigned int val;
+	int ret, reg = to_reg(gpio, CTRL_IN);
 
-	if (gpio > CRYSTALCOVE_VGPIO_NUM)
+	if (reg < 0)
 		return 0;
 
-	ret = regmap_read(cg->regmap, to_reg(gpio, CTRL_IN), &val);
+	ret = regmap_read(cg->regmap, reg, &val);
 	if (ret)
 		return ret;
 
@@ -170,14 +180,15 @@ static void crystalcove_gpio_set(struct
 				 unsigned gpio, int value)
 {
 	struct crystalcove_gpio *cg = gpiochip_get_data(chip);
+	int reg = to_reg(gpio, CTRL_OUT);
 
-	if (gpio > CRYSTALCOVE_VGPIO_NUM)
+	if (reg < 0)
 		return;
 
 	if (value)
-		regmap_update_bits(cg->regmap, to_reg(gpio, CTRL_OUT), 1, 1);
+		regmap_update_bits(cg->regmap, reg, 1, 1);
 	else
-		regmap_update_bits(cg->regmap, to_reg(gpio, CTRL_OUT), 1, 0);
+		regmap_update_bits(cg->regmap, reg, 1, 0);
 }
 
 static int crystalcove_irq_type(struct irq_data *data, unsigned type)
@@ -185,6 +196,9 @@ static int crystalcove_irq_type(struct i
 	struct crystalcove_gpio *cg =
 		gpiochip_get_data(irq_data_get_irq_chip_data(data));
 
+	if (data->hwirq >= CRYSTALCOVE_GPIO_NUM)
+		return 0;
+
 	switch (type) {
 	case IRQ_TYPE_NONE:
 		cg->intcnt_value = CTLI_INTCNT_DIS;
@@ -235,8 +249,10 @@ static void crystalcove_irq_unmask(struc
 	struct crystalcove_gpio *cg =
 		gpiochip_get_data(irq_data_get_irq_chip_data(data));
 
-	cg->set_irq_mask = false;
-	cg->update |= UPDATE_IRQ_MASK;
+	if (data->hwirq < CRYSTALCOVE_GPIO_NUM) {
+		cg->set_irq_mask = false;
+		cg->update |= UPDATE_IRQ_MASK;
+	}
 }
 
 static void crystalcove_irq_mask(struct irq_data *data)
@@ -244,8 +260,10 @@ static void crystalcove_irq_mask(struct
 	struct crystalcove_gpio *cg =
 		gpiochip_get_data(irq_data_get_irq_chip_data(data));
 
-	cg->set_irq_mask = true;
-	cg->update |= UPDATE_IRQ_MASK;
+	if (data->hwirq < CRYSTALCOVE_GPIO_NUM) {
+		cg->set_irq_mask = true;
+		cg->update |= UPDATE_IRQ_MASK;
+	}
 }
 
 static struct irq_chip crystalcove_irqchip = {


Patches currently in stable-queue which might be from hdegoede@redhat.com are

queue-4.9/gpio-crystalcove-do-not-write-regular-gpio-registers-for-virtual-gpios.patch
queue-4.9/acpi-video-default-lcd_only-to-true-on-win8-ready-and-newer-machines.patch
queue-4.9/hid-i2c-call-acpi_device_fix_up_power-for-acpi-enumerated-devices.patch
queue-4.9/ata-libahci-properly-propagate-return-value-of-platform_get_irq.patch
queue-4.9/input-goodix-disable-irqs-while-suspended.patch
queue-4.9/asoc-intel-cht_bsw_rt5645-analog-mic-support.patch
queue-4.9/pinctrl-baytrail-enable-glitch-filter-for-gpios-used-as-interrupts.patch

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2018-04-09 20:01 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-04-09 19:58 Patch "gpio: crystalcove: Do not write regular gpio registers for virtual GPIOs" has been added to the 4.9-stable tree gregkh

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).