[PATCH] drivers: pinctrl: add a pin_base for sparse gpio-ranges
From: Chanho Park
Date: Wed Oct 26 2011 - 00:22:25 EST
This patch enables mapping a base offset of gpio ranges with
a pin offset even if does'nt matched. A base of pinctrl_gpio_range
means a base offset of gpio. However, we cannot convert gpio to pin
number for sparse gpio ranges just only using a gpio base offset.
We can convert a gpio to real pin number(even if not matched) using
a new pin_base which means a base pin offset of requested gpio range.
For example, let's assume below two gpio ranges in the system.
static struct pinctrl_gpio_range gpio_range_a = {
.name = "chip a",
.id = 0,
.base = 32,
.pin_base = 32,
.npins = 16,
.gc = &chip_a;
};
static struct pinctrl_gpio_range gpio_range_b = {
.name = "chip b",
.id = 0,
.base = 48,
.pin_base = 64,
.npins = 8,
.gc = &chip_b;
};
{
struct pinctrl_dev *pctl;
...
pinctrl_add_gpio_range(pctl, &gpio_range_a);
pinctrl_add_gpio_range(pctl, &gpio_range_b);
}
We can calucalate a exact pin ranges even if doesn't matched with gpio ranges.
chip a:
gpio-range : [32 .. 47]
pin-range : [32 .. 47]
chip b:
gpio-range : [48 .. 55]
pin-range : [64 .. 71]
Signed-off-by: Chanho Park <chanho61.park@xxxxxxxxxxx>
Signed-off-by: Kyungmin Park <kyungmin.park@xxxxxxxxxxx>
---
Documentation/pinctrl.txt | 42 ++++++++------------------------------
drivers/pinctrl/pinmux-sirf.c | 4 +++
drivers/pinctrl/pinmux-u300.c | 1 +
drivers/pinctrl/pinmux.c | 4 +-
include/linux/pinctrl/pinctrl.h | 2 +
5 files changed, 18 insertions(+), 35 deletions(-)
diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt
index 328adb7..41244e4 100644
--- a/Documentation/pinctrl.txt
+++ b/Documentation/pinctrl.txt
@@ -265,14 +265,16 @@ static struct pinctrl_gpio_range gpio_range_a = {
.name = "chip a",
.id = 0,
.base = 32,
+ .pin_base = 32,
.npins = 16,
.gc = &chip_a;
};
-static struct pinctrl_gpio_range gpio_range_a = {
+static struct pinctrl_gpio_range gpio_range_b = {
.name = "chip b",
.id = 0,
.base = 48,
+ .pin_base = 64,
.npins = 8,
.gc = &chip_b;
};
@@ -289,38 +291,12 @@ So this complex system has one pin controller handling two different
GPIO chips. Chip a has 16 pins and chip b has 8 pins. They are mapped in
the global GPIO pin space at:
-chip a: [32 .. 47]
-chip b: [48 .. 55]
-
-When GPIO-specific functions in the pin control subsystem are called, these
-ranges will be used to look up the apropriate pin controller by inspecting
-and matching the pin to the pin ranges across all controllers. When a
-pin controller handling the matching range is found, GPIO-specific functions
-will be called on that specific pin controller.
-
-For all functionalities dealing with pin biasing, pin muxing etc, the pin
-controller subsystem will subtract the range's .base offset from the passed
-in gpio pin number, and pass that on to the pin control driver, so the driver
-will get an offset into its handled number range. Further it is also passed
-the range ID value, so that the pin controller knows which range it should
-deal with.
-
-For example: if a user issues pinctrl_gpio_set_foo(50), the pin control
-subsystem will find that the second range on this pin controller matches,
-subtract the base 48 and call the
-pinctrl_driver_gpio_set_foo(pinctrl, range, 2) where the latter function has
-this signature:
-
-int pinctrl_driver_gpio_set_foo(struct pinctrl_dev *pctldev,
- struct pinctrl_gpio_range *rangeid,
- unsigned offset);
-
-Now the driver knows that we want to do some GPIO-specific operation on the
-second GPIO range handled by "chip b", at offset 2 in that specific range.
-
-(If the GPIO subsystem is ever refactored to use a local per-GPIO controller
-pin space, this mapping will need to be augmented accordingly.)
-
+chip a:
+ gpio-range : [32 .. 47]
+ pin-range : [32 .. 47]
+chip b:
+ gpio-range : [48 .. 55]
+ pin-range : [64 .. 71]
PINMUX interfaces
=================
diff --git a/drivers/pinctrl/pinmux-sirf.c b/drivers/pinctrl/pinmux-sirf.c
index ba73523..c9c277f 100644
--- a/drivers/pinctrl/pinmux-sirf.c
+++ b/drivers/pinctrl/pinmux-sirf.c
@@ -1100,21 +1100,25 @@ static struct pinctrl_gpio_range sirfsoc_gpio_ranges[] = {
.name = "sirfsoc-gpio*",
.id = 0,
.base = 0,
+ .pin_base = 0,
.npins = 32,
}, {
.name = "sirfsoc-gpio*",
.id = 1,
.base = 32,
+ .pin_base = 32,
.npins = 32,
}, {
.name = "sirfsoc-gpio*",
.id = 2,
.base = 64,
+ .pin_base = 64,
.npins = 32,
}, {
.name = "sirfsoc-gpio*",
.id = 3,
.base = 96,
+ .pin_base = 96,
.npins = 19,
},
};
diff --git a/drivers/pinctrl/pinmux-u300.c b/drivers/pinctrl/pinmux-u300.c
index 4858a64..dab0cfe 100644
--- a/drivers/pinctrl/pinmux-u300.c
+++ b/drivers/pinctrl/pinmux-u300.c
@@ -1023,6 +1023,7 @@ static struct pinctrl_gpio_range u300_gpio_range = {
.name = "COH901*",
.id = 0,
.base = 0,
+ .pin_base = 0,
.npins = 64,
};
diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c
index 5c4b782..d1384da 100644
--- a/drivers/pinctrl/pinmux.c
+++ b/drivers/pinctrl/pinmux.c
@@ -225,7 +225,7 @@ int pinmux_request_gpio(unsigned gpio)
return -EINVAL;
/* Convert to the pin controllers number space */
- pin = gpio - range->base;
+ pin = gpio - range->base + range->pin_base;
/* Conjure some name stating what chip and pin this is taken by */
snprintf(gpiostr, 15, "%s:%d", range->name, gpio);
@@ -258,7 +258,7 @@ void pinmux_free_gpio(unsigned gpio)
return;
/* Convert to the pin controllers number space */
- pin = gpio - range->base;
+ pin = gpio - range->base + range->pin_base;
pin_free(pctldev, pin, true);
}
diff --git a/include/linux/pinctrl/pinctrl.h b/include/linux/pinctrl/pinctrl.h
index 90dd28b..7768e44 100644
--- a/include/linux/pinctrl/pinctrl.h
+++ b/include/linux/pinctrl/pinctrl.h
@@ -127,6 +127,7 @@ struct pinctrl_pin_desc {
* @name: a name for the chip in this range
* @id: an ID number for the chip in this range
* @base: base offset of the GPIO range
+ * @pin_base: base pin offset of the GPIO range
* @npins: number of pins in the GPIO range, including the base number
* @gc: an optional pointer to a gpio_chip
*/
@@ -135,6 +136,7 @@ struct pinctrl_gpio_range {
const char *name;
unsigned int id;
unsigned int base;
+ unsigned int pin_base;
unsigned int npins;
struct gpio_chip *gc;
};
--
1.7.5.4
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/