Skip to content

Commit a60eac3

Browse files
westerilinusw
authored andcommitted
pinctrl: intel: Allow custom GPIO base for pad groups
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> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
1 parent 03c4749 commit a60eac3

File tree

2 files changed

+120
-39
lines changed

2 files changed

+120
-39
lines changed

drivers/pinctrl/intel/pinctrl-intel.c

Lines changed: 117 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -806,22 +806,63 @@ static const struct gpio_chip intel_gpio_chip = {
806806
.set_config = gpiochip_generic_config,
807807
};
808808

809+
/**
810+
* intel_gpio_to_pin() - Translate from GPIO offset to pin number
811+
* @pctrl: Pinctrl structure
812+
* @offset: GPIO offset from gpiolib
813+
* @commmunity: Community is filled here if not %NULL
814+
* @padgrp: Pad group is filled here if not %NULL
815+
*
816+
* When coming through gpiolib irqchip, the GPIO offset is not
817+
* automatically translated to pinctrl pin number. This function can be
818+
* used to find out the corresponding pinctrl pin.
819+
*/
820+
static int intel_gpio_to_pin(struct intel_pinctrl *pctrl, unsigned offset,
821+
const struct intel_community **community,
822+
const struct intel_padgroup **padgrp)
823+
{
824+
int i;
825+
826+
for (i = 0; i < pctrl->ncommunities; i++) {
827+
const struct intel_community *comm = &pctrl->communities[i];
828+
int j;
829+
830+
for (j = 0; j < comm->ngpps; j++) {
831+
const struct intel_padgroup *pgrp = &comm->gpps[j];
832+
833+
if (pgrp->gpio_base < 0)
834+
continue;
835+
836+
if (offset >= pgrp->gpio_base &&
837+
offset < pgrp->gpio_base + pgrp->size) {
838+
int pin;
839+
840+
pin = pgrp->base + offset - pgrp->gpio_base;
841+
if (community)
842+
*community = comm;
843+
if (padgrp)
844+
*padgrp = pgrp;
845+
846+
return pin;
847+
}
848+
}
849+
}
850+
851+
return -EINVAL;
852+
}
853+
809854
static void intel_gpio_irq_ack(struct irq_data *d)
810855
{
811856
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
812857
struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
813858
const struct intel_community *community;
814-
unsigned pin = irqd_to_hwirq(d);
859+
const struct intel_padgroup *padgrp;
860+
int pin;
815861

816-
community = intel_get_community(pctrl, pin);
817-
if (community) {
818-
const struct intel_padgroup *padgrp;
862+
pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), &community, &padgrp);
863+
if (pin >= 0) {
819864
unsigned gpp, gpp_offset, is_offset;
820865

821-
padgrp = intel_community_get_padgroup(community, pin);
822-
if (!padgrp)
823-
return;
824-
825866
gpp = padgrp->reg_num;
826867
gpp_offset = padgroup_offset(padgrp, pin);
827868
is_offset = community->is_offset + gpp * 4;
@@ -837,19 +878,15 @@ static void intel_gpio_irq_enable(struct irq_data *d)
837878
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
838879
struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
839880
const struct intel_community *community;
840-
unsigned pin = irqd_to_hwirq(d);
881+
const struct intel_padgroup *padgrp;
882+
int pin;
841883

842-
community = intel_get_community(pctrl, pin);
843-
if (community) {
844-
const struct intel_padgroup *padgrp;
884+
pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), &community, &padgrp);
885+
if (pin >= 0) {
845886
unsigned gpp, gpp_offset, is_offset;
846887
unsigned long flags;
847888
u32 value;
848889

849-
padgrp = intel_community_get_padgroup(community, pin);
850-
if (!padgrp)
851-
return;
852-
853890
gpp = padgrp->reg_num;
854891
gpp_offset = padgroup_offset(padgrp, pin);
855892
is_offset = community->is_offset + gpp * 4;
@@ -870,20 +907,16 @@ static void intel_gpio_irq_mask_unmask(struct irq_data *d, bool mask)
870907
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
871908
struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
872909
const struct intel_community *community;
873-
unsigned pin = irqd_to_hwirq(d);
910+
const struct intel_padgroup *padgrp;
911+
int pin;
874912

875-
community = intel_get_community(pctrl, pin);
876-
if (community) {
877-
const struct intel_padgroup *padgrp;
913+
pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), &community, &padgrp);
914+
if (pin >= 0) {
878915
unsigned gpp, gpp_offset;
879916
unsigned long flags;
880917
void __iomem *reg;
881918
u32 value;
882919

883-
padgrp = intel_community_get_padgroup(community, pin);
884-
if (!padgrp)
885-
return;
886-
887920
gpp = padgrp->reg_num;
888921
gpp_offset = padgroup_offset(padgrp, pin);
889922

@@ -914,7 +947,7 @@ static int intel_gpio_irq_type(struct irq_data *d, unsigned type)
914947
{
915948
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
916949
struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
917-
unsigned pin = irqd_to_hwirq(d);
950+
unsigned pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), NULL, NULL);
918951
unsigned long flags;
919952
void __iomem *reg;
920953
u32 value;
@@ -969,7 +1002,7 @@ static int intel_gpio_irq_wake(struct irq_data *d, unsigned int on)
9691002
{
9701003
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
9711004
struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
972-
unsigned pin = irqd_to_hwirq(d);
1005+
unsigned pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), NULL, NULL);
9731006

9741007
if (on)
9751008
enable_irq_wake(pctrl->irq);
@@ -1000,14 +1033,10 @@ static irqreturn_t intel_gpio_community_irq_handler(struct intel_pinctrl *pctrl,
10001033
pending &= enabled;
10011034

10021035
for_each_set_bit(gpp_offset, &pending, padgrp->size) {
1003-
unsigned padno, irq;
1004-
1005-
padno = padgrp->base - community->pin_base + gpp_offset;
1006-
if (padno >= community->npins)
1007-
break;
1036+
unsigned irq;
10081037

10091038
irq = irq_find_mapping(gc->irq.domain,
1010-
community->pin_base + padno);
1039+
padgrp->gpio_base + gpp_offset);
10111040
generic_handle_irq(irq);
10121041

10131042
ret |= IRQ_HANDLED;
@@ -1044,13 +1073,56 @@ static struct irq_chip intel_gpio_irqchip = {
10441073
.flags = IRQCHIP_MASK_ON_SUSPEND,
10451074
};
10461075

1076+
static int intel_gpio_add_pin_ranges(struct intel_pinctrl *pctrl,
1077+
const struct intel_community *community)
1078+
{
1079+
int ret, i;
1080+
1081+
for (i = 0; i < community->ngpps; i++) {
1082+
const struct intel_padgroup *gpp = &community->gpps[i];
1083+
1084+
if (gpp->gpio_base < 0)
1085+
continue;
1086+
1087+
ret = gpiochip_add_pin_range(&pctrl->chip, dev_name(pctrl->dev),
1088+
gpp->gpio_base, gpp->base,
1089+
gpp->size);
1090+
if (ret)
1091+
return ret;
1092+
}
1093+
1094+
return ret;
1095+
}
1096+
1097+
static unsigned intel_gpio_ngpio(const struct intel_pinctrl *pctrl)
1098+
{
1099+
const struct intel_community *community;
1100+
unsigned ngpio = 0;
1101+
int i, j;
1102+
1103+
for (i = 0; i < pctrl->ncommunities; i++) {
1104+
community = &pctrl->communities[i];
1105+
for (j = 0; j < community->ngpps; j++) {
1106+
const struct intel_padgroup *gpp = &community->gpps[j];
1107+
1108+
if (gpp->gpio_base < 0)
1109+
continue;
1110+
1111+
if (gpp->gpio_base + gpp->size > ngpio)
1112+
ngpio = gpp->gpio_base + gpp->size;
1113+
}
1114+
}
1115+
1116+
return ngpio;
1117+
}
1118+
10471119
static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq)
10481120
{
1049-
int ret;
1121+
int ret, i;
10501122

10511123
pctrl->chip = intel_gpio_chip;
10521124

1053-
pctrl->chip.ngpio = pctrl->soc->npins;
1125+
pctrl->chip.ngpio = intel_gpio_ngpio(pctrl);
10541126
pctrl->chip.label = dev_name(pctrl->dev);
10551127
pctrl->chip.parent = pctrl->dev;
10561128
pctrl->chip.base = -1;
@@ -1062,11 +1134,14 @@ static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq)
10621134
return ret;
10631135
}
10641136

1065-
ret = gpiochip_add_pin_range(&pctrl->chip, dev_name(pctrl->dev),
1066-
0, 0, pctrl->soc->npins);
1067-
if (ret) {
1068-
dev_err(pctrl->dev, "failed to add GPIO pin range\n");
1069-
return ret;
1137+
for (i = 0; i < pctrl->ncommunities; i++) {
1138+
struct intel_community *community = &pctrl->communities[i];
1139+
1140+
ret = intel_gpio_add_pin_ranges(pctrl, community);
1141+
if (ret) {
1142+
dev_err(pctrl->dev, "failed to add GPIO pin range\n");
1143+
return ret;
1144+
}
10701145
}
10711146

10721147
/*
@@ -1126,6 +1201,9 @@ static int intel_pinctrl_add_padgroups(struct intel_pinctrl *pctrl,
11261201
if (gpps[i].size > 32)
11271202
return -EINVAL;
11281203

1204+
if (!gpps[i].gpio_base)
1205+
gpps[i].gpio_base = gpps[i].base;
1206+
11291207
gpps[i].padown_num = padown_num;
11301208

11311209
/*

drivers/pinctrl/intel/pinctrl-intel.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ struct intel_function {
5151
* @reg_num: GPI_IS register number
5252
* @base: Starting pin of this group
5353
* @size: Size of this group (maximum is 32).
54+
* @gpio_base: Starting GPIO base of this group (%0 if matches with @base,
55+
* and %-1 if no GPIO mapping should be created)
5456
* @padown_num: PAD_OWN register number (assigned by the core driver)
5557
*
5658
* If pad groups of a community are not the same size, use this structure
@@ -60,6 +62,7 @@ struct intel_padgroup {
6062
unsigned reg_num;
6163
unsigned base;
6264
unsigned size;
65+
int gpio_base;
6366
unsigned padown_num;
6467
};
6568

0 commit comments

Comments
 (0)