linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] pinctrl: Align Cannon Lake GPIO number space with Windows
@ 2017-11-27 13:54 Mika Westerberg
  2017-11-27 13:54 ` [PATCH 1/3] gpio / ACPI: Drop unnecessary ACPI GPIO to Linux GPIO translation Mika Westerberg
                   ` (4 more replies)
  0 siblings, 5 replies; 10+ messages in thread
From: Mika Westerberg @ 2017-11-27 13:54 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Andy Shevchenko, Heikki Krogerus, Rafael J. Wysocki,
	Hans de Goede, Takashi Iwai, Mika Westerberg, linux-acpi,
	linux-kernel

Hi,

It turns out that the Cannon Lake GPIO driver in Windows uses different
GPIO numbering scheme than what Linux uses. Instead of hardware numbers it
has "banks" of 32 pins even if the hardware group actually does not have
that many pins. This is problematic for Linux because BIOS uses the same
Windows numbering scheme in ACPI GpioIo/GpioInt resources, making Linux to
pick a wrong pin.

For example the SD card detection GPIO resource in BIOS ACPI tables looks
like:

  GpioInt (...) {231} // vSD3_CD_B

Where the real hardware number would be 180 instead of 231.

Unfortunately changing the BIOS and the Windows driver is not possible for
Cannon Lake anymore so we need to handle it in Linux instead. This should
be done properly in future platforms.

The patch series updates the Intel pinctrl driver to allow passing custom
GPIO number space, taking advantage of pin ranges supported by the pinctrl
core. However, before we can add these pin ranges we need to drop the
custom Cherryview GPIO/ACPI translation first and make the driver to use
direct mapping instead (which turns out to be much simpler).

Once that is done we update the Cannon Lake pinctrl driver to align with
the Windows GPIO driver numbering scheme.

Mika Westerberg (3):
  gpio / ACPI: Drop unnecessary ACPI GPIO to Linux GPIO translation
  pinctrl: intel: Allow custom GPIO base for pad groups
  pinctrl: cannonlake: Align GPIO number space with Windows

 drivers/gpio/gpiolib-acpi.c                |  75 +-------------
 drivers/pinctrl/intel/pinctrl-cannonlake.c |  65 ++++++------
 drivers/pinctrl/intel/pinctrl-cherryview.c |  59 ++++-------
 drivers/pinctrl/intel/pinctrl-intel.c      | 156 +++++++++++++++++++++--------
 drivers/pinctrl/intel/pinctrl-intel.h      |   3 +
 5 files changed, 176 insertions(+), 182 deletions(-)

-- 
2.15.0

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/3] gpio / ACPI: Drop unnecessary ACPI GPIO to Linux GPIO translation
  2017-11-27 13:54 [PATCH 0/3] pinctrl: Align Cannon Lake GPIO number space with Windows Mika Westerberg
@ 2017-11-27 13:54 ` Mika Westerberg
  2017-11-28 21:05   ` Rafael J. Wysocki
  2017-11-29 12:43   ` Linus Walleij
  2017-11-27 13:54 ` [PATCH 2/3] pinctrl: intel: Allow custom GPIO base for pad groups Mika Westerberg
                   ` (3 subsequent siblings)
  4 siblings, 2 replies; 10+ messages in thread
From: Mika Westerberg @ 2017-11-27 13:54 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Andy Shevchenko, Heikki Krogerus, Rafael J. Wysocki,
	Hans de Goede, Takashi Iwai, Mika Westerberg, linux-acpi,
	linux-kernel

We added acpi_gpiochip_pin_to_gpio_offset() because there was a need to
translate from ACPI GpioIo/GpioInt number to Linux GPIO number in the
Cherryview pinctrl driver. This translation is necessary because
Cherryview has gaps in the pin list and the driver used continuous GPIO
number space in Linux side as follows:

  created GPIO range 0->7 ==> INT33FF:03 PIN 0->7
  created GPIO range 8->19 ==> INT33FF:03 PIN 15->26
  created GPIO range 20->25 ==> INT33FF:03 PIN 30->35
  created GPIO range 26->33 ==> INT33FF:03 PIN 45->52
  created GPIO range 34->43 ==> INT33FF:03 PIN 60->69
  created GPIO range 44->54 ==> INT33FF:03 PIN 75->85

For example when ACPI GpioInt resource refers to GPIO 81 (SDMMC3_CD_B)
we translate from pin 81 to the corresponding Linux GPIO number, which
is 50. This number is then used when the GPIO is accessed through gpiolib.

It turns out, this is not necessary at all. We can just pass 1:1 mapping
between Linux GPIO numbers and pin numbers (including gaps) and the
pinctrl core handles all the details automatically:

  created GPIO range 0->7 ==> INT33FF:03 PIN 0->7
  created GPIO range 15->26 ==> INT33FF:03 PIN 15->26
  created GPIO range 30->35 ==> INT33FF:03 PIN 30->35
  created GPIO range 45->52 ==> INT33FF:03 PIN 45->52
  created GPIO range 60->69 ==> INT33FF:03 PIN 60->69
  created GPIO range 75->85 ==> INT33FF:03 PIN 75->85

Here GPIO 81 is exactly same than the hardware pin 81 (SDMMC3_CD_B).

As an added bonus this simplifies both the ACPI GPIO core code and the
Cherryview pinctrl driver.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
 drivers/gpio/gpiolib-acpi.c                | 75 +-----------------------------
 drivers/pinctrl/intel/pinctrl-cherryview.c | 59 ++++++++---------------
 2 files changed, 22 insertions(+), 112 deletions(-)

diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
index eb4528c87c0b..b77c544bf7e2 100644
--- a/drivers/gpio/gpiolib-acpi.c
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -58,58 +58,6 @@ static int acpi_gpiochip_find(struct gpio_chip *gc, void *data)
 	return ACPI_HANDLE(gc->parent) == data;
 }
 
-#ifdef CONFIG_PINCTRL
-/**
- * acpi_gpiochip_pin_to_gpio_offset() - translates ACPI GPIO to Linux GPIO
- * @gdev: GPIO device
- * @pin: ACPI GPIO pin number from GpioIo/GpioInt resource
- *
- * Function takes ACPI GpioIo/GpioInt pin number as a parameter and
- * translates it to a corresponding offset suitable to be passed to a
- * GPIO controller driver.
- *
- * Typically the returned offset is same as @pin, but if the GPIO
- * controller uses pin controller and the mapping is not contiguous the
- * offset might be different.
- */
-static int acpi_gpiochip_pin_to_gpio_offset(struct gpio_device *gdev, int pin)
-{
-	struct gpio_pin_range *pin_range;
-
-	/* If there are no ranges in this chip, use 1:1 mapping */
-	if (list_empty(&gdev->pin_ranges))
-		return pin;
-
-	list_for_each_entry(pin_range, &gdev->pin_ranges, node) {
-		const struct pinctrl_gpio_range *range = &pin_range->range;
-		int i;
-
-		if (range->pins) {
-			for (i = 0; i < range->npins; i++) {
-				if (range->pins[i] == pin)
-					return range->base + i - gdev->base;
-			}
-		} else {
-			if (pin >= range->pin_base &&
-			    pin < range->pin_base + range->npins) {
-				unsigned gpio_base;
-
-				gpio_base = range->base - gdev->base;
-				return gpio_base + pin - range->pin_base;
-			}
-		}
-	}
-
-	return -EINVAL;
-}
-#else
-static inline int acpi_gpiochip_pin_to_gpio_offset(struct gpio_device *gdev,
-						   int pin)
-{
-	return pin;
-}
-#endif
-
 /**
  * acpi_get_gpiod() - Translate ACPI GPIO pin to GPIO descriptor usable with GPIO API
  * @path:	ACPI GPIO controller full path name, (e.g. "\\_SB.GPO1")
@@ -125,7 +73,6 @@ static struct gpio_desc *acpi_get_gpiod(char *path, int pin)
 	struct gpio_chip *chip;
 	acpi_handle handle;
 	acpi_status status;
-	int offset;
 
 	status = acpi_get_handle(NULL, path, &handle);
 	if (ACPI_FAILURE(status))
@@ -135,11 +82,7 @@ static struct gpio_desc *acpi_get_gpiod(char *path, int pin)
 	if (!chip)
 		return ERR_PTR(-EPROBE_DEFER);
 
-	offset = acpi_gpiochip_pin_to_gpio_offset(chip->gpiodev, pin);
-	if (offset < 0)
-		return ERR_PTR(offset);
-
-	return gpiochip_get_desc(chip, offset);
+	return gpiochip_get_desc(chip, pin);
 }
 
 static irqreturn_t acpi_gpio_irq_handler(int irq, void *data)
@@ -216,10 +159,6 @@ static acpi_status acpi_gpiochip_request_interrupt(struct acpi_resource *ares,
 	if (!handler)
 		return AE_OK;
 
-	pin = acpi_gpiochip_pin_to_gpio_offset(chip->gpiodev, pin);
-	if (pin < 0)
-		return AE_BAD_PARAMETER;
-
 	desc = gpiochip_request_own_desc(chip, pin, "ACPI:Event");
 	if (IS_ERR(desc)) {
 		dev_err(chip->parent, "Failed to request GPIO\n");
@@ -852,12 +791,6 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,
 		struct gpio_desc *desc;
 		bool found;
 
-		pin = acpi_gpiochip_pin_to_gpio_offset(chip->gpiodev, pin);
-		if (pin < 0) {
-			status = AE_BAD_PARAMETER;
-			goto out;
-		}
-
 		mutex_lock(&achip->conn_lock);
 
 		found = false;
@@ -990,11 +923,7 @@ static struct gpio_desc *acpi_gpiochip_parse_own_gpio(
 	if (ret < 0)
 		return ERR_PTR(ret);
 
-	ret = acpi_gpiochip_pin_to_gpio_offset(chip->gpiodev, gpios[0]);
-	if (ret < 0)
-		return ERR_PTR(ret);
-
-	desc = gpiochip_get_desc(chip, ret);
+	desc = gpiochip_get_desc(chip, gpios[0]);
 	if (IS_ERR(desc))
 		return desc;
 
diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c
index bdedb6325c72..aa6c9f569c2b 100644
--- a/drivers/pinctrl/intel/pinctrl-cherryview.c
+++ b/drivers/pinctrl/intel/pinctrl-cherryview.c
@@ -131,10 +131,8 @@ struct chv_gpio_pinrange {
  * @ngroups: Number of groups
  * @functions: All functions in this community
  * @nfunctions: Number of functions
- * @ngpios: Number of GPIOs in this community
  * @gpio_ranges: An array of GPIO ranges in this community
  * @ngpio_ranges: Number of GPIO ranges
- * @ngpios: Total number of GPIOs in this community
  * @nirqs: Total number of IRQs this community can generate
  */
 struct chv_community {
@@ -147,7 +145,6 @@ struct chv_community {
 	size_t nfunctions;
 	const struct chv_gpio_pinrange *gpio_ranges;
 	size_t ngpio_ranges;
-	size_t ngpios;
 	size_t nirqs;
 	acpi_adr_space_type acpi_space_id;
 };
@@ -399,7 +396,6 @@ static const struct chv_community southwest_community = {
 	.nfunctions = ARRAY_SIZE(southwest_functions),
 	.gpio_ranges = southwest_gpio_ranges,
 	.ngpio_ranges = ARRAY_SIZE(southwest_gpio_ranges),
-	.ngpios = ARRAY_SIZE(southwest_pins),
 	/*
 	 * Southwest community can benerate GPIO interrupts only for the
 	 * first 8 interrupts. The upper half (8-15) can only be used to
@@ -489,7 +485,6 @@ static const struct chv_community north_community = {
 	.npins = ARRAY_SIZE(north_pins),
 	.gpio_ranges = north_gpio_ranges,
 	.ngpio_ranges = ARRAY_SIZE(north_gpio_ranges),
-	.ngpios = ARRAY_SIZE(north_pins),
 	/*
 	 * North community can generate GPIO interrupts only for the first
 	 * 8 interrupts. The upper half (8-15) can only be used to trigger
@@ -538,7 +533,6 @@ static const struct chv_community east_community = {
 	.npins = ARRAY_SIZE(east_pins),
 	.gpio_ranges = east_gpio_ranges,
 	.ngpio_ranges = ARRAY_SIZE(east_gpio_ranges),
-	.ngpios = ARRAY_SIZE(east_pins),
 	.nirqs = 16,
 	.acpi_space_id = 0x93,
 };
@@ -665,7 +659,6 @@ static const struct chv_community southeast_community = {
 	.nfunctions = ARRAY_SIZE(southeast_functions),
 	.gpio_ranges = southeast_gpio_ranges,
 	.ngpio_ranges = ARRAY_SIZE(southeast_gpio_ranges),
-	.ngpios = ARRAY_SIZE(southeast_pins),
 	.nirqs = 16,
 	.acpi_space_id = 0x94,
 };
@@ -1253,21 +1246,14 @@ static struct pinctrl_desc chv_pinctrl_desc = {
 	.owner = THIS_MODULE,
 };
 
-static unsigned chv_gpio_offset_to_pin(struct chv_pinctrl *pctrl,
-				       unsigned offset)
-{
-	return pctrl->community->pins[offset].number;
-}
-
 static int chv_gpio_get(struct gpio_chip *chip, unsigned offset)
 {
 	struct chv_pinctrl *pctrl = gpiochip_get_data(chip);
-	int pin = chv_gpio_offset_to_pin(pctrl, offset);
 	unsigned long flags;
 	u32 ctrl0, cfg;
 
 	raw_spin_lock_irqsave(&chv_lock, flags);
-	ctrl0 = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0));
+	ctrl0 = readl(chv_padreg(pctrl, offset, CHV_PADCTRL0));
 	raw_spin_unlock_irqrestore(&chv_lock, flags);
 
 	cfg = ctrl0 & CHV_PADCTRL0_GPIOCFG_MASK;
@@ -1281,14 +1267,13 @@ static int chv_gpio_get(struct gpio_chip *chip, unsigned offset)
 static void chv_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 {
 	struct chv_pinctrl *pctrl = gpiochip_get_data(chip);
-	unsigned pin = chv_gpio_offset_to_pin(pctrl, offset);
 	unsigned long flags;
 	void __iomem *reg;
 	u32 ctrl0;
 
 	raw_spin_lock_irqsave(&chv_lock, flags);
 
-	reg = chv_padreg(pctrl, pin, CHV_PADCTRL0);
+	reg = chv_padreg(pctrl, offset, CHV_PADCTRL0);
 	ctrl0 = readl(reg);
 
 	if (value)
@@ -1304,12 +1289,11 @@ static void chv_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 static int chv_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
 {
 	struct chv_pinctrl *pctrl = gpiochip_get_data(chip);
-	unsigned pin = chv_gpio_offset_to_pin(pctrl, offset);
 	u32 ctrl0, direction;
 	unsigned long flags;
 
 	raw_spin_lock_irqsave(&chv_lock, flags);
-	ctrl0 = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0));
+	ctrl0 = readl(chv_padreg(pctrl, offset, CHV_PADCTRL0));
 	raw_spin_unlock_irqrestore(&chv_lock, flags);
 
 	direction = ctrl0 & CHV_PADCTRL0_GPIOCFG_MASK;
@@ -1345,7 +1329,7 @@ static void chv_gpio_irq_ack(struct irq_data *d)
 {
 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
 	struct chv_pinctrl *pctrl = gpiochip_get_data(gc);
-	int pin = chv_gpio_offset_to_pin(pctrl, irqd_to_hwirq(d));
+	int pin = irqd_to_hwirq(d);
 	u32 intr_line;
 
 	raw_spin_lock(&chv_lock);
@@ -1362,7 +1346,7 @@ static void chv_gpio_irq_mask_unmask(struct irq_data *d, bool mask)
 {
 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
 	struct chv_pinctrl *pctrl = gpiochip_get_data(gc);
-	int pin = chv_gpio_offset_to_pin(pctrl, irqd_to_hwirq(d));
+	int pin = irqd_to_hwirq(d);
 	u32 value, intr_line;
 	unsigned long flags;
 
@@ -1407,8 +1391,7 @@ static unsigned chv_gpio_irq_startup(struct irq_data *d)
 	if (irqd_get_trigger_type(d) == IRQ_TYPE_NONE) {
 		struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
 		struct chv_pinctrl *pctrl = gpiochip_get_data(gc);
-		unsigned offset = irqd_to_hwirq(d);
-		int pin = chv_gpio_offset_to_pin(pctrl, offset);
+		unsigned pin = irqd_to_hwirq(d);
 		irq_flow_handler_t handler;
 		unsigned long flags;
 		u32 intsel, value;
@@ -1426,7 +1409,7 @@ static unsigned chv_gpio_irq_startup(struct irq_data *d)
 
 		if (!pctrl->intr_lines[intsel]) {
 			irq_set_handler_locked(d, handler);
-			pctrl->intr_lines[intsel] = offset;
+			pctrl->intr_lines[intsel] = pin;
 		}
 		raw_spin_unlock_irqrestore(&chv_lock, flags);
 	}
@@ -1439,8 +1422,7 @@ static int chv_gpio_irq_type(struct irq_data *d, unsigned type)
 {
 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
 	struct chv_pinctrl *pctrl = gpiochip_get_data(gc);
-	unsigned offset = irqd_to_hwirq(d);
-	int pin = chv_gpio_offset_to_pin(pctrl, offset);
+	unsigned pin = irqd_to_hwirq(d);
 	unsigned long flags;
 	u32 value;
 
@@ -1486,7 +1468,7 @@ static int chv_gpio_irq_type(struct irq_data *d, unsigned type)
 	value &= CHV_PADCTRL0_INTSEL_MASK;
 	value >>= CHV_PADCTRL0_INTSEL_SHIFT;
 
-	pctrl->intr_lines[value] = offset;
+	pctrl->intr_lines[value] = pin;
 
 	if (type & IRQ_TYPE_EDGE_BOTH)
 		irq_set_handler_locked(d, handle_edge_irq);
@@ -1576,12 +1558,12 @@ static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq)
 	const struct chv_gpio_pinrange *range;
 	struct gpio_chip *chip = &pctrl->chip;
 	bool need_valid_mask = !dmi_check_system(chv_no_valid_mask);
-	int ret, i, offset;
-	int irq_base;
+	const struct chv_community *community = pctrl->community;
+	int ret, i, irq_base;
 
 	*chip = chv_gpio_chip;
 
-	chip->ngpio = pctrl->community->ngpios;
+	chip->ngpio = community->pins[community->npins - 1].number + 1;
 	chip->label = dev_name(pctrl->dev);
 	chip->parent = pctrl->dev;
 	chip->base = -1;
@@ -1593,30 +1575,29 @@ static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq)
 		return ret;
 	}
 
-	for (i = 0, offset = 0; i < pctrl->community->ngpio_ranges; i++) {
-		range = &pctrl->community->gpio_ranges[i];
-		ret = gpiochip_add_pin_range(chip, dev_name(pctrl->dev), offset,
-					     range->base, range->npins);
+	for (i = 0; i < community->ngpio_ranges; i++) {
+		range = &community->gpio_ranges[i];
+		ret = gpiochip_add_pin_range(chip, dev_name(pctrl->dev),
+					     range->base, range->base,
+					     range->npins);
 		if (ret) {
 			dev_err(pctrl->dev, "failed to add GPIO pin range\n");
 			return ret;
 		}
-
-		offset += range->npins;
 	}
 
 	/* Do not add GPIOs that can only generate GPEs to the IRQ domain */
-	for (i = 0; i < pctrl->community->npins; i++) {
+	for (i = 0; i < community->npins; i++) {
 		const struct pinctrl_pin_desc *desc;
 		u32 intsel;
 
-		desc = &pctrl->community->pins[i];
+		desc = &community->pins[i];
 
 		intsel = readl(chv_padreg(pctrl, desc->number, CHV_PADCTRL0));
 		intsel &= CHV_PADCTRL0_INTSEL_MASK;
 		intsel >>= CHV_PADCTRL0_INTSEL_SHIFT;
 
-		if (need_valid_mask && intsel >= pctrl->community->nirqs)
+		if (need_valid_mask && intsel >= community->nirqs)
 			clear_bit(i, chip->irq.valid_mask);
 	}
 
-- 
2.15.0

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/3] pinctrl: intel: Allow custom GPIO base for pad groups
  2017-11-27 13:54 [PATCH 0/3] pinctrl: Align Cannon Lake GPIO number space with Windows Mika Westerberg
  2017-11-27 13:54 ` [PATCH 1/3] gpio / ACPI: Drop unnecessary ACPI GPIO to Linux GPIO translation Mika Westerberg
@ 2017-11-27 13:54 ` Mika Westerberg
  2017-11-29 12:46   ` Linus Walleij
  2017-11-27 13:54 ` [PATCH 3/3] pinctrl: cannonlake: Align GPIO number space with Windows Mika Westerberg
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 10+ messages in thread
From: Mika Westerberg @ 2017-11-27 13:54 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Andy Shevchenko, Heikki Krogerus, Rafael J. Wysocki,
	Hans de Goede, Takashi Iwai, Mika Westerberg, linux-acpi,
	linux-kernel

Currently we always have direct mapping between GPIO numbers and the
hardware pin numbers. However, there are cases where that's not the case
anymore (more about this in the next patch). Instead we need to be able
to specify custom GPIO base for certain pad groups.

To support this, add a new field (gpio_base) to the pad group structure
and update the core Intel pinctrl driver to handle this accordingly.
Passing 0 as gpio_base will use direct mapping so the existing drivers
do not need to be modified. Passing -1 excludes the whole pad group from
having GPIO mapping.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
 drivers/pinctrl/intel/pinctrl-intel.c | 156 +++++++++++++++++++++++++---------
 drivers/pinctrl/intel/pinctrl-intel.h |   3 +
 2 files changed, 120 insertions(+), 39 deletions(-)

diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c
index 3544c9fcf598..f54d66723892 100644
--- a/drivers/pinctrl/intel/pinctrl-intel.c
+++ b/drivers/pinctrl/intel/pinctrl-intel.c
@@ -811,22 +811,63 @@ static const struct gpio_chip intel_gpio_chip = {
 	.set_config = gpiochip_generic_config,
 };
 
+/**
+ * intel_gpio_to_pin() - Translate from GPIO offset to pin number
+ * @pctrl: Pinctrl structure
+ * @offset: GPIO offset from gpiolib
+ * @commmunity: Community is filled here if not %NULL
+ * @padgrp: Pad group is filled here if not %NULL
+ *
+ * When coming through gpiolib irqchip, the GPIO offset is not
+ * automatically translated to pinctrl pin number. This function can be
+ * used to find out the corresponding pinctrl pin.
+ */
+static int intel_gpio_to_pin(struct intel_pinctrl *pctrl, unsigned offset,
+			     const struct intel_community **community,
+			     const struct intel_padgroup **padgrp)
+{
+	int i;
+
+	for (i = 0; i < pctrl->ncommunities; i++) {
+		const struct intel_community *comm = &pctrl->communities[i];
+		int j;
+
+		for (j = 0; j < comm->ngpps; j++) {
+			const struct intel_padgroup *pgrp = &comm->gpps[j];
+
+			if (pgrp->gpio_base < 0)
+				continue;
+
+			if (offset >= pgrp->gpio_base &&
+			    offset < pgrp->gpio_base + pgrp->size) {
+				int pin;
+
+				pin = pgrp->base + offset - pgrp->gpio_base;
+				if (community)
+					*community = comm;
+				if (padgrp)
+					*padgrp = pgrp;
+
+				return pin;
+			}
+		}
+	}
+
+	return -EINVAL;
+}
+
 static void intel_gpio_irq_ack(struct irq_data *d)
 {
 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
 	struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
 	const struct intel_community *community;
-	unsigned pin = irqd_to_hwirq(d);
+	const struct intel_padgroup *padgrp;
+	int pin;
 
-	community = intel_get_community(pctrl, pin);
-	if (community) {
-		const struct intel_padgroup *padgrp;
+	pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), &community, &padgrp);
+	if (pin >= 0) {
 		unsigned gpp, gpp_offset, is_offset;
 
-		padgrp = intel_community_get_padgroup(community, pin);
-		if (!padgrp)
-			return;
-
 		gpp = padgrp->reg_num;
 		gpp_offset = padgroup_offset(padgrp, pin);
 		is_offset = community->is_offset + gpp * 4;
@@ -842,19 +883,15 @@ static void intel_gpio_irq_enable(struct irq_data *d)
 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
 	struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
 	const struct intel_community *community;
-	unsigned pin = irqd_to_hwirq(d);
+	const struct intel_padgroup *padgrp;
+	int pin;
 
-	community = intel_get_community(pctrl, pin);
-	if (community) {
-		const struct intel_padgroup *padgrp;
+	pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), &community, &padgrp);
+	if (pin >= 0) {
 		unsigned gpp, gpp_offset, is_offset;
 		unsigned long flags;
 		u32 value;
 
-		padgrp = intel_community_get_padgroup(community, pin);
-		if (!padgrp)
-			return;
-
 		gpp = padgrp->reg_num;
 		gpp_offset = padgroup_offset(padgrp, pin);
 		is_offset = community->is_offset + gpp * 4;
@@ -875,20 +912,16 @@ static void intel_gpio_irq_mask_unmask(struct irq_data *d, bool mask)
 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
 	struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
 	const struct intel_community *community;
-	unsigned pin = irqd_to_hwirq(d);
+	const struct intel_padgroup *padgrp;
+	int pin;
 
-	community = intel_get_community(pctrl, pin);
-	if (community) {
-		const struct intel_padgroup *padgrp;
+	pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), &community, &padgrp);
+	if (pin >= 0) {
 		unsigned gpp, gpp_offset;
 		unsigned long flags;
 		void __iomem *reg;
 		u32 value;
 
-		padgrp = intel_community_get_padgroup(community, pin);
-		if (!padgrp)
-			return;
-
 		gpp = padgrp->reg_num;
 		gpp_offset = padgroup_offset(padgrp, pin);
 
@@ -919,7 +952,7 @@ static int intel_gpio_irq_type(struct irq_data *d, unsigned type)
 {
 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
 	struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
-	unsigned pin = irqd_to_hwirq(d);
+	unsigned pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), NULL, NULL);
 	unsigned long flags;
 	void __iomem *reg;
 	u32 value;
@@ -976,7 +1009,7 @@ static int intel_gpio_irq_wake(struct irq_data *d, unsigned int on)
 {
 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
 	struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
-	unsigned pin = irqd_to_hwirq(d);
+	unsigned pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), NULL, NULL);
 
 	if (on)
 		enable_irq_wake(pctrl->irq);
@@ -1007,14 +1040,10 @@ static irqreturn_t intel_gpio_community_irq_handler(struct intel_pinctrl *pctrl,
 		pending &= enabled;
 
 		for_each_set_bit(gpp_offset, &pending, padgrp->size) {
-			unsigned padno, irq;
-
-			padno = padgrp->base - community->pin_base + gpp_offset;
-			if (padno >= community->npins)
-				break;
+			unsigned irq;
 
 			irq = irq_find_mapping(gc->irq.domain,
-					       community->pin_base + padno);
+					       padgrp->gpio_base + gpp_offset);
 			generic_handle_irq(irq);
 
 			ret |= IRQ_HANDLED;
@@ -1051,13 +1080,56 @@ static struct irq_chip intel_gpio_irqchip = {
 	.flags = IRQCHIP_MASK_ON_SUSPEND,
 };
 
+static int intel_gpio_add_pin_ranges(struct intel_pinctrl *pctrl,
+				     const struct intel_community *community)
+{
+	int ret, i;
+
+	for (i = 0; i < community->ngpps; i++) {
+		const struct intel_padgroup *gpp = &community->gpps[i];
+
+		if (gpp->gpio_base < 0)
+			continue;
+
+		ret = gpiochip_add_pin_range(&pctrl->chip, dev_name(pctrl->dev),
+					     gpp->gpio_base, gpp->base,
+					     gpp->size);
+		if (ret)
+			return ret;
+	}
+
+	return ret;
+}
+
+static unsigned intel_gpio_ngpio(const struct intel_pinctrl *pctrl)
+{
+	const struct intel_community *community;
+	unsigned ngpio = 0;
+	int i, j;
+
+	for (i = 0; i < pctrl->ncommunities; i++) {
+		community = &pctrl->communities[i];
+		for (j = 0; j < community->ngpps; j++) {
+			const struct intel_padgroup *gpp = &community->gpps[j];
+
+			if (gpp->gpio_base < 0)
+				continue;
+
+			if (gpp->gpio_base + gpp->size > ngpio)
+				ngpio = gpp->gpio_base + gpp->size;
+		}
+	}
+
+	return ngpio;
+}
+
 static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq)
 {
-	int ret;
+	int ret, i;
 
 	pctrl->chip = intel_gpio_chip;
 
-	pctrl->chip.ngpio = pctrl->soc->npins;
+	pctrl->chip.ngpio = intel_gpio_ngpio(pctrl);
 	pctrl->chip.label = dev_name(pctrl->dev);
 	pctrl->chip.parent = pctrl->dev;
 	pctrl->chip.base = -1;
@@ -1069,11 +1141,14 @@ static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq)
 		return ret;
 	}
 
-	ret = gpiochip_add_pin_range(&pctrl->chip, dev_name(pctrl->dev),
-				     0, 0, pctrl->soc->npins);
-	if (ret) {
-		dev_err(pctrl->dev, "failed to add GPIO pin range\n");
-		return ret;
+	for (i = 0; i < pctrl->ncommunities; i++) {
+		struct intel_community *community = &pctrl->communities[i];
+
+		ret = intel_gpio_add_pin_ranges(pctrl, community);
+		if (ret) {
+			dev_err(pctrl->dev, "failed to add GPIO pin range\n");
+			return ret;
+		}
 	}
 
 	/*
@@ -1133,6 +1208,9 @@ static int intel_pinctrl_add_padgroups(struct intel_pinctrl *pctrl,
 		if (gpps[i].size > 32)
 			return -EINVAL;
 
+		if (!gpps[i].gpio_base)
+			gpps[i].gpio_base = gpps[i].base;
+
 		gpps[i].padown_num = padown_num;
 
 		/*
diff --git a/drivers/pinctrl/intel/pinctrl-intel.h b/drivers/pinctrl/intel/pinctrl-intel.h
index 13b0bd6eb2a2..98fdf9adf623 100644
--- a/drivers/pinctrl/intel/pinctrl-intel.h
+++ b/drivers/pinctrl/intel/pinctrl-intel.h
@@ -51,6 +51,8 @@ struct intel_function {
  * @reg_num: GPI_IS register number
  * @base: Starting pin of this group
  * @size: Size of this group (maximum is 32).
+ * @gpio_base: Starting GPIO base of this group (%0 if matches with @base,
+ *	       and %-1 if no GPIO mapping should be created)
  * @padown_num: PAD_OWN register number (assigned by the core driver)
  *
  * If pad groups of a community are not the same size, use this structure
@@ -60,6 +62,7 @@ struct intel_padgroup {
 	unsigned reg_num;
 	unsigned base;
 	unsigned size;
+	int gpio_base;
 	unsigned padown_num;
 };
 
-- 
2.15.0

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/3] pinctrl: cannonlake: Align GPIO number space with Windows
  2017-11-27 13:54 [PATCH 0/3] pinctrl: Align Cannon Lake GPIO number space with Windows Mika Westerberg
  2017-11-27 13:54 ` [PATCH 1/3] gpio / ACPI: Drop unnecessary ACPI GPIO to Linux GPIO translation Mika Westerberg
  2017-11-27 13:54 ` [PATCH 2/3] pinctrl: intel: Allow custom GPIO base for pad groups Mika Westerberg
@ 2017-11-27 13:54 ` Mika Westerberg
  2017-11-28 21:52 ` [PATCH 0/3] pinctrl: Align Cannon Lake " Andy Shevchenko
  2017-11-29 12:49 ` Linus Walleij
  4 siblings, 0 replies; 10+ messages in thread
From: Mika Westerberg @ 2017-11-27 13:54 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Andy Shevchenko, Heikki Krogerus, Rafael J. Wysocki,
	Hans de Goede, Takashi Iwai, Mika Westerberg, linux-acpi,
	linux-kernel

The Cannon Lake Windows GPIO driver always exposes 32 pins per "bank"
regardless of whether the hardware actually has that many pins in a pad
group. This means that there are gaps in the GPIO number space even if
such gaps do not exist in the real hardware. To make things worse the
BIOS is also using the same scheme, so for example on Cannon Lake-LP
vGPIO 39 (vSD3_CD_B) the ACPI GpioInt resource has number 231 instead of
the expected 180 (which would be the hardware number).

To make SD card detection and other GPIOs working properly in Linux we
align the pinctrl-cannonlake GPIO numbering to follow the Windows GPIO
driver numbering taking advantage of the gpio_base field introduced in
the previous patch.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
 drivers/pinctrl/intel/pinctrl-cannonlake.c | 65 ++++++++++++++++--------------
 1 file changed, 34 insertions(+), 31 deletions(-)

diff --git a/drivers/pinctrl/intel/pinctrl-cannonlake.c b/drivers/pinctrl/intel/pinctrl-cannonlake.c
index e130599be571..6243e7d95e7e 100644
--- a/drivers/pinctrl/intel/pinctrl-cannonlake.c
+++ b/drivers/pinctrl/intel/pinctrl-cannonlake.c
@@ -23,13 +23,16 @@
 #define CNL_HOSTSW_OWN	0x0b0
 #define CNL_GPI_IE	0x120
 
-#define CNL_GPP(r, s, e)				\
+#define CNL_GPP(r, s, e, g)				\
 	{						\
 		.reg_num = (r),				\
 		.base = (s),				\
 		.size = ((e) - (s) + 1),		\
+		.gpio_base = (g),			\
 	}
 
+#define CNL_NO_GPIO	-1
+
 #define CNL_COMMUNITY(b, s, e, g)			\
 	{						\
 		.barno = (b),				\
@@ -363,32 +366,32 @@ static const struct pinctrl_pin_desc cnlh_pins[] = {
 };
 
 static const struct intel_padgroup cnlh_community0_gpps[] = {
-	CNL_GPP(0, 0, 24),	/* GPP_A */
-	CNL_GPP(1, 25, 50),	/* GPP_B */
+	CNL_GPP(0, 0, 24, 0),			/* GPP_A */
+	CNL_GPP(1, 25, 50, 32),			/* GPP_B */
 };
 
 static const struct intel_padgroup cnlh_community1_gpps[] = {
-	CNL_GPP(0, 51, 74),	/* GPP_C */
-	CNL_GPP(1, 75, 98),	/* GPP_D */
-	CNL_GPP(2, 99, 106),	/* GPP_G */
-	CNL_GPP(3, 107, 114),	/* AZA */
-	CNL_GPP(4, 115, 146),	/* vGPIO_0 */
-	CNL_GPP(5, 147, 154),	/* vGPIO_1 */
+	CNL_GPP(0, 51, 74, 64),			/* GPP_C */
+	CNL_GPP(1, 75, 98, 96),			/* GPP_D */
+	CNL_GPP(2, 99, 106, 128),		/* GPP_G */
+	CNL_GPP(3, 107, 114, CNL_NO_GPIO),	/* AZA */
+	CNL_GPP(4, 115, 146, 160),		/* vGPIO_0 */
+	CNL_GPP(5, 147, 154, CNL_NO_GPIO),	/* vGPIO_1 */
 };
 
 static const struct intel_padgroup cnlh_community3_gpps[] = {
-	CNL_GPP(0, 155, 178),	/* GPP_K */
-	CNL_GPP(1, 179, 202),	/* GPP_H */
-	CNL_GPP(2, 203, 215),	/* GPP_E */
-	CNL_GPP(3, 216, 239),	/* GPP_F */
-	CNL_GPP(4, 240, 248),	/* SPI */
+	CNL_GPP(0, 155, 178, 192),		/* GPP_K */
+	CNL_GPP(1, 179, 202, 224),		/* GPP_H */
+	CNL_GPP(2, 203, 215, 258),		/* GPP_E */
+	CNL_GPP(3, 216, 239, 288),		/* GPP_F */
+	CNL_GPP(4, 240, 248, CNL_NO_GPIO),	/* SPI */
 };
 
 static const struct intel_padgroup cnlh_community4_gpps[] = {
-	CNL_GPP(0, 249, 259),	/* CPU */
-	CNL_GPP(1, 260, 268),	/* JTAG */
-	CNL_GPP(2, 269, 286),	/* GPP_I */
-	CNL_GPP(3, 287, 298),	/* GPP_J */
+	CNL_GPP(0, 249, 259, CNL_NO_GPIO),	/* CPU */
+	CNL_GPP(1, 260, 268, CNL_NO_GPIO),	/* JTAG */
+	CNL_GPP(2, 269, 286, 320),		/* GPP_I */
+	CNL_GPP(3, 287, 298, 352),		/* GPP_J */
 };
 
 static const unsigned int cnlh_spi0_pins[] = { 40, 41, 42, 43 };
@@ -785,25 +788,25 @@ static const struct intel_function cnllp_functions[] = {
 };
 
 static const struct intel_padgroup cnllp_community0_gpps[] = {
-	CNL_GPP(0, 0, 24),	/* GPP_A */
-	CNL_GPP(1, 25, 50),	/* GPP_B */
-	CNL_GPP(2, 51, 58),	/* GPP_G */
-	CNL_GPP(3, 59, 67),	/* SPI */
+	CNL_GPP(0, 0, 24, 0),			/* GPP_A */
+	CNL_GPP(1, 25, 50, 32),			/* GPP_B */
+	CNL_GPP(2, 51, 58, 64),			/* GPP_G */
+	CNL_GPP(3, 59, 67, CNL_NO_GPIO),	/* SPI */
 };
 
 static const struct intel_padgroup cnllp_community1_gpps[] = {
-	CNL_GPP(0, 68, 92),	/* GPP_D */
-	CNL_GPP(1, 93, 116),	/* GPP_F */
-	CNL_GPP(2, 117, 140),	/* GPP_H */
-	CNL_GPP(3, 141, 172),	/* vGPIO */
-	CNL_GPP(4, 173, 180),	/* vGPIO */
+	CNL_GPP(0, 68, 92, 96),			/* GPP_D */
+	CNL_GPP(1, 93, 116, 128),		/* GPP_F */
+	CNL_GPP(2, 117, 140, 160),		/* GPP_H */
+	CNL_GPP(3, 141, 172, 192),		/* vGPIO */
+	CNL_GPP(4, 173, 180, 224),		/* vGPIO */
 };
 
 static const struct intel_padgroup cnllp_community4_gpps[] = {
-	CNL_GPP(0, 181, 204),	/* GPP_C */
-	CNL_GPP(1, 205, 228),	/* GPP_E */
-	CNL_GPP(2, 229, 237),	/* JTAG */
-	CNL_GPP(3, 238, 243),	/* HVCMOS */
+	CNL_GPP(0, 181, 204, 256),		/* GPP_C */
+	CNL_GPP(1, 205, 228, 288),		/* GPP_E */
+	CNL_GPP(2, 229, 237, CNL_NO_GPIO),	/* JTAG */
+	CNL_GPP(3, 238, 243, CNL_NO_GPIO),	/* HVCMOS */
 };
 
 static const struct intel_community cnllp_communities[] = {
-- 
2.15.0

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/3] gpio / ACPI: Drop unnecessary ACPI GPIO to Linux GPIO translation
  2017-11-27 13:54 ` [PATCH 1/3] gpio / ACPI: Drop unnecessary ACPI GPIO to Linux GPIO translation Mika Westerberg
@ 2017-11-28 21:05   ` Rafael J. Wysocki
  2017-11-29 12:43   ` Linus Walleij
  1 sibling, 0 replies; 10+ messages in thread
From: Rafael J. Wysocki @ 2017-11-28 21:05 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: Linus Walleij, Andy Shevchenko, Heikki Krogerus,
	Rafael J. Wysocki, Hans de Goede, Takashi Iwai,
	ACPI Devel Maling List, Linux Kernel Mailing List

On Mon, Nov 27, 2017 at 2:54 PM, Mika Westerberg
<mika.westerberg@linux.intel.com> wrote:
> We added acpi_gpiochip_pin_to_gpio_offset() because there was a need to
> translate from ACPI GpioIo/GpioInt number to Linux GPIO number in the
> Cherryview pinctrl driver. This translation is necessary because
> Cherryview has gaps in the pin list and the driver used continuous GPIO
> number space in Linux side as follows:
>
>   created GPIO range 0->7 ==> INT33FF:03 PIN 0->7
>   created GPIO range 8->19 ==> INT33FF:03 PIN 15->26
>   created GPIO range 20->25 ==> INT33FF:03 PIN 30->35
>   created GPIO range 26->33 ==> INT33FF:03 PIN 45->52
>   created GPIO range 34->43 ==> INT33FF:03 PIN 60->69
>   created GPIO range 44->54 ==> INT33FF:03 PIN 75->85
>
> For example when ACPI GpioInt resource refers to GPIO 81 (SDMMC3_CD_B)
> we translate from pin 81 to the corresponding Linux GPIO number, which
> is 50. This number is then used when the GPIO is accessed through gpiolib.
>
> It turns out, this is not necessary at all. We can just pass 1:1 mapping
> between Linux GPIO numbers and pin numbers (including gaps) and the
> pinctrl core handles all the details automatically:
>
>   created GPIO range 0->7 ==> INT33FF:03 PIN 0->7
>   created GPIO range 15->26 ==> INT33FF:03 PIN 15->26
>   created GPIO range 30->35 ==> INT33FF:03 PIN 30->35
>   created GPIO range 45->52 ==> INT33FF:03 PIN 45->52
>   created GPIO range 60->69 ==> INT33FF:03 PIN 60->69
>   created GPIO range 75->85 ==> INT33FF:03 PIN 75->85
>
> Here GPIO 81 is exactly same than the hardware pin 81 (SDMMC3_CD_B).
>
> As an added bonus this simplifies both the ACPI GPIO core code and the
> Cherryview pinctrl driver.

Cool!

Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/3] pinctrl: Align Cannon Lake GPIO number space with Windows
  2017-11-27 13:54 [PATCH 0/3] pinctrl: Align Cannon Lake GPIO number space with Windows Mika Westerberg
                   ` (2 preceding siblings ...)
  2017-11-27 13:54 ` [PATCH 3/3] pinctrl: cannonlake: Align GPIO number space with Windows Mika Westerberg
@ 2017-11-28 21:52 ` Andy Shevchenko
  2017-11-29 12:49 ` Linus Walleij
  4 siblings, 0 replies; 10+ messages in thread
From: Andy Shevchenko @ 2017-11-28 21:52 UTC (permalink / raw)
  To: Mika Westerberg, Linus Walleij
  Cc: Heikki Krogerus, Rafael J. Wysocki, Hans de Goede, Takashi Iwai,
	linux-acpi, linux-kernel

On Mon, 2017-11-27 at 16:54 +0300, Mika Westerberg wrote:
> Hi,
> 
> It turns out that the Cannon Lake GPIO driver in Windows uses
> different
> GPIO numbering scheme than what Linux uses. Instead of hardware
> numbers it
> has "banks" of 32 pins even if the hardware group actually does not
> have
> that many pins. This is problematic for Linux because BIOS uses the
> same
> Windows numbering scheme in ACPI GpioIo/GpioInt resources, making
> Linux to
> pick a wrong pin.
> 
> For example the SD card detection GPIO resource in BIOS ACPI tables
> looks
> like:
> 
>   GpioInt (...) {231} // vSD3_CD_B
> 
> Where the real hardware number would be 180 instead of 231.
> 
> Unfortunately changing the BIOS and the Windows driver is not possible
> for
> Cannon Lake anymore so we need to handle it in Linux instead. This
> should
> be done properly in future platforms.
> 
> The patch series updates the Intel pinctrl driver to allow passing
> custom
> GPIO number space, taking advantage of pin ranges supported by the
> pinctrl
> core. However, before we can add these pin ranges we need to drop the
> custom Cherryview GPIO/ACPI translation first and make the driver to
> use
> direct mapping instead (which turns out to be much simpler).
> 
> Once that is done we update the Cannon Lake pinctrl driver to align
> with
> the Windows GPIO driver numbering scheme.

For all three:

Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

> 
> Mika Westerberg (3):
>   gpio / ACPI: Drop unnecessary ACPI GPIO to Linux GPIO translation
>   pinctrl: intel: Allow custom GPIO base for pad groups
>   pinctrl: cannonlake: Align GPIO number space with Windows
> 
>  drivers/gpio/gpiolib-acpi.c                |  75 +-------------
>  drivers/pinctrl/intel/pinctrl-cannonlake.c |  65 ++++++------
>  drivers/pinctrl/intel/pinctrl-cherryview.c |  59 ++++-------
>  drivers/pinctrl/intel/pinctrl-intel.c      | 156
> +++++++++++++++++++++--------
>  drivers/pinctrl/intel/pinctrl-intel.h      |   3 +
>  5 files changed, 176 insertions(+), 182 deletions(-)
> 

-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/3] gpio / ACPI: Drop unnecessary ACPI GPIO to Linux GPIO translation
  2017-11-27 13:54 ` [PATCH 1/3] gpio / ACPI: Drop unnecessary ACPI GPIO to Linux GPIO translation Mika Westerberg
  2017-11-28 21:05   ` Rafael J. Wysocki
@ 2017-11-29 12:43   ` Linus Walleij
  1 sibling, 0 replies; 10+ messages in thread
From: Linus Walleij @ 2017-11-29 12:43 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: Andy Shevchenko, Heikki Krogerus, Rafael J. Wysocki,
	Hans de Goede, Takashi Iwai, ACPI Devel Maling List,
	linux-kernel

On Mon, Nov 27, 2017 at 2:54 PM, Mika Westerberg
<mika.westerberg@linux.intel.com> wrote:

> We added acpi_gpiochip_pin_to_gpio_offset() because there was a need to
> translate from ACPI GpioIo/GpioInt number to Linux GPIO number in the
> Cherryview pinctrl driver. This translation is necessary because
> Cherryview has gaps in the pin list and the driver used continuous GPIO
> number space in Linux side as follows:
>
>   created GPIO range 0->7 ==> INT33FF:03 PIN 0->7
>   created GPIO range 8->19 ==> INT33FF:03 PIN 15->26
>   created GPIO range 20->25 ==> INT33FF:03 PIN 30->35
>   created GPIO range 26->33 ==> INT33FF:03 PIN 45->52
>   created GPIO range 34->43 ==> INT33FF:03 PIN 60->69
>   created GPIO range 44->54 ==> INT33FF:03 PIN 75->85
>
> For example when ACPI GpioInt resource refers to GPIO 81 (SDMMC3_CD_B)
> we translate from pin 81 to the corresponding Linux GPIO number, which
> is 50. This number is then used when the GPIO is accessed through gpiolib.
>
> It turns out, this is not necessary at all. We can just pass 1:1 mapping
> between Linux GPIO numbers and pin numbers (including gaps) and the
> pinctrl core handles all the details automatically:
>
>   created GPIO range 0->7 ==> INT33FF:03 PIN 0->7
>   created GPIO range 15->26 ==> INT33FF:03 PIN 15->26
>   created GPIO range 30->35 ==> INT33FF:03 PIN 30->35
>   created GPIO range 45->52 ==> INT33FF:03 PIN 45->52
>   created GPIO range 60->69 ==> INT33FF:03 PIN 60->69
>   created GPIO range 75->85 ==> INT33FF:03 PIN 75->85
>
> Here GPIO 81 is exactly same than the hardware pin 81 (SDMMC3_CD_B).
>
> As an added bonus this simplifies both the ACPI GPIO core code and the
> Cherryview pinctrl driver.
>
> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>

I optimistically applied this with the ACKs to the pinctrl tree hoping
it does not
clash with Andy's refactorings that I applied to the GPIO tree.

Let's see what happens.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/3] pinctrl: intel: Allow custom GPIO base for pad groups
  2017-11-27 13:54 ` [PATCH 2/3] pinctrl: intel: Allow custom GPIO base for pad groups Mika Westerberg
@ 2017-11-29 12:46   ` Linus Walleij
  0 siblings, 0 replies; 10+ messages in thread
From: Linus Walleij @ 2017-11-29 12:46 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: Andy Shevchenko, Heikki Krogerus, Rafael J. Wysocki,
	Hans de Goede, Takashi Iwai, ACPI Devel Maling List,
	linux-kernel

On Mon, Nov 27, 2017 at 2:54 PM, Mika Westerberg
<mika.westerberg@linux.intel.com> wrote:

> Currently we always have direct mapping between GPIO numbers and the
> hardware pin numbers. However, there are cases where that's not the case
> anymore (more about this in the next patch). Instead we need to be able
> to specify custom GPIO base for certain pad groups.
>
> To support this, add a new field (gpio_base) to the pad group structure
> and update the core Intel pinctrl driver to handle this accordingly.
> Passing 0 as gpio_base will use direct mapping so the existing drivers
> do not need to be modified. Passing -1 excludes the whole pad group from
> having GPIO mapping.
>
> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>

Patch applied with Andy's ACK.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/3] pinctrl: Align Cannon Lake GPIO number space with Windows
  2017-11-27 13:54 [PATCH 0/3] pinctrl: Align Cannon Lake GPIO number space with Windows Mika Westerberg
                   ` (3 preceding siblings ...)
  2017-11-28 21:52 ` [PATCH 0/3] pinctrl: Align Cannon Lake " Andy Shevchenko
@ 2017-11-29 12:49 ` Linus Walleij
  2017-11-29 13:09   ` Mika Westerberg
  4 siblings, 1 reply; 10+ messages in thread
From: Linus Walleij @ 2017-11-29 12:49 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: Andy Shevchenko, Heikki Krogerus, Rafael J. Wysocki,
	Hans de Goede, Takashi Iwai, ACPI Devel Maling List,
	linux-kernel

On Mon, Nov 27, 2017 at 2:54 PM, Mika Westerberg
<mika.westerberg@linux.intel.com> wrote:

> It turns out that the Cannon Lake GPIO driver in Windows uses different
> GPIO numbering scheme than what Linux uses. Instead of hardware numbers it
> has "banks" of 32 pins even if the hardware group actually does not have
> that many pins. This is problematic for Linux because BIOS uses the same
> Windows numbering scheme in ACPI GpioIo/GpioInt resources, making Linux to
> pick a wrong pin.
>
> For example the SD card detection GPIO resource in BIOS ACPI tables looks
> like:
>
>   GpioInt (...) {231} // vSD3_CD_B
>
> Where the real hardware number would be 180 instead of 231.
>
> Unfortunately changing the BIOS and the Windows driver is not possible for
> Cannon Lake anymore so we need to handle it in Linux instead. This should
> be done properly in future platforms.
>
> The patch series updates the Intel pinctrl driver to allow passing custom
> GPIO number space, taking advantage of pin ranges supported by the pinctrl
> core. However, before we can add these pin ranges we need to drop the
> custom Cherryview GPIO/ACPI translation first and make the driver to use
> direct mapping instead (which turns out to be much simpler).
>
> Once that is done we update the Cannon Lake pinctrl driver to align with
> the Windows GPIO driver numbering scheme.
>
> Mika Westerberg (3):
>   gpio / ACPI: Drop unnecessary ACPI GPIO to Linux GPIO translation
>   pinctrl: intel: Allow custom GPIO base for pad groups
>   pinctrl: cannonlake: Align GPIO number space with Windows

I applied these with Andy's ACKs.

I guess I vageuly understand what happened.

So the ACPI GPIO numberspace was misaligned with the
actual hardware GPIO numberspace. That's unfortunate.

I hope these is nothing in here trying to align the *LINUX*
global GPIO numberspace with this weirdness and that
lsgpio still gives something reasonable per-gpiochip?

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/3] pinctrl: Align Cannon Lake GPIO number space with Windows
  2017-11-29 12:49 ` Linus Walleij
@ 2017-11-29 13:09   ` Mika Westerberg
  0 siblings, 0 replies; 10+ messages in thread
From: Mika Westerberg @ 2017-11-29 13:09 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Andy Shevchenko, Heikki Krogerus, Rafael J. Wysocki,
	Hans de Goede, Takashi Iwai, ACPI Devel Maling List,
	linux-kernel

On Wed, Nov 29, 2017 at 01:49:01PM +0100, Linus Walleij wrote:
> On Mon, Nov 27, 2017 at 2:54 PM, Mika Westerberg
> <mika.westerberg@linux.intel.com> wrote:
> 
> > It turns out that the Cannon Lake GPIO driver in Windows uses different
> > GPIO numbering scheme than what Linux uses. Instead of hardware numbers it
> > has "banks" of 32 pins even if the hardware group actually does not have
> > that many pins. This is problematic for Linux because BIOS uses the same
> > Windows numbering scheme in ACPI GpioIo/GpioInt resources, making Linux to
> > pick a wrong pin.
> >
> > For example the SD card detection GPIO resource in BIOS ACPI tables looks
> > like:
> >
> >   GpioInt (...) {231} // vSD3_CD_B
> >
> > Where the real hardware number would be 180 instead of 231.
> >
> > Unfortunately changing the BIOS and the Windows driver is not possible for
> > Cannon Lake anymore so we need to handle it in Linux instead. This should
> > be done properly in future platforms.
> >
> > The patch series updates the Intel pinctrl driver to allow passing custom
> > GPIO number space, taking advantage of pin ranges supported by the pinctrl
> > core. However, before we can add these pin ranges we need to drop the
> > custom Cherryview GPIO/ACPI translation first and make the driver to use
> > direct mapping instead (which turns out to be much simpler).
> >
> > Once that is done we update the Cannon Lake pinctrl driver to align with
> > the Windows GPIO driver numbering scheme.
> >
> > Mika Westerberg (3):
> >   gpio / ACPI: Drop unnecessary ACPI GPIO to Linux GPIO translation
> >   pinctrl: intel: Allow custom GPIO base for pad groups
> >   pinctrl: cannonlake: Align GPIO number space with Windows
> 
> I applied these with Andy's ACKs.

Thanks!

> I guess I vageuly understand what happened.
> 
> So the ACPI GPIO numberspace was misaligned with the
> actual hardware GPIO numberspace. That's unfortunate.

That's right.

> I hope these is nothing in here trying to align the *LINUX*
> global GPIO numberspace with this weirdness and that
> lsgpio still gives something reasonable per-gpiochip?

The resulting GPIO ranges for the chip look like following on the
problematic system:

# cat /sys/kernel/debug/pinctrl/INT34BB\:00/gpio-ranges 
GPIO ranges handled:
0: INT34BB:00 GPIOS [200 - 224] PINS [0 - 24]
32: INT34BB:00 GPIOS [232 - 257] PINS [25 - 50]
64: INT34BB:00 GPIOS [264 - 271] PINS [51 - 58]
96: INT34BB:00 GPIOS [296 - 320] PINS [68 - 92]
128: INT34BB:00 GPIOS [328 - 351] PINS [93 - 116]
160: INT34BB:00 GPIOS [360 - 383] PINS [117 - 140]
192: INT34BB:00 GPIOS [392 - 423] PINS [141 - 172]
224: INT34BB:00 GPIOS [424 - 431] PINS [173 - 180]
256: INT34BB:00 GPIOS [456 - 479] PINS [181 - 204]
288: INT34BB:00 GPIOS [488 - 511] PINS [205 - 228]

So we will have GPIO ranges for each pad group starting at 32 pin
"boundary" to align it with what the BIOS expects. Pinctrl pin numbers
still follow the hardware numbering and is continuous.

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2017-11-29 13:09 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-11-27 13:54 [PATCH 0/3] pinctrl: Align Cannon Lake GPIO number space with Windows Mika Westerberg
2017-11-27 13:54 ` [PATCH 1/3] gpio / ACPI: Drop unnecessary ACPI GPIO to Linux GPIO translation Mika Westerberg
2017-11-28 21:05   ` Rafael J. Wysocki
2017-11-29 12:43   ` Linus Walleij
2017-11-27 13:54 ` [PATCH 2/3] pinctrl: intel: Allow custom GPIO base for pad groups Mika Westerberg
2017-11-29 12:46   ` Linus Walleij
2017-11-27 13:54 ` [PATCH 3/3] pinctrl: cannonlake: Align GPIO number space with Windows Mika Westerberg
2017-11-28 21:52 ` [PATCH 0/3] pinctrl: Align Cannon Lake " Andy Shevchenko
2017-11-29 12:49 ` Linus Walleij
2017-11-29 13:09   ` Mika Westerberg

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).