@@ -28,6 +28,7 @@
.padcfglock_offset = BXT_PADCFGLOCK, \
.hostown_offset = BXT_HOSTSW_OWN, \
.ie_offset = BXT_GPI_IE, \
+ .gpp_size = 32, \
.pin_base = (s), \
.npins = ((e) - (s) + 1), \
}
@@ -37,6 +37,7 @@
#define PADOWN_BITS 4
#define PADOWN_SHIFT(p) ((p) % 8 * PADOWN_BITS)
#define PADOWN_MASK(p) (0xf << PADOWN_SHIFT(p))
+#define PADOWN_GPP(p) ((p)/8)
/* Offset from pad_regs */
#define PADCFG0 0x000
@@ -108,6 +109,14 @@ struct intel_pinctrl {
#define gpiochip_to_pinctrl(c) container_of(c, struct intel_pinctrl, chip)
#define pin_to_padno(c, p) ((p) - (c)->pin_base)
+static unsigned intel_npads_in_gpp(const struct intel_community *community)
+{
+ if (!community || !community->gpp_size)
+ return NPADS_IN_GPP;
+ else
+ return community->gpp_size;
+}
+
static struct intel_community *intel_get_community(struct intel_pinctrl *pctrl,
unsigned pin)
{
@@ -142,7 +151,7 @@ static void __iomem *intel_get_padcfg(struct intel_pinctrl *pctrl, unsigned pin,
static bool intel_pad_owned_by_host(struct intel_pinctrl *pctrl, unsigned pin)
{
const struct intel_community *community;
- unsigned padno, gpp, gpp_offset, offset;
+ unsigned padno, gpp, offset;
void __iomem *padown;
community = intel_get_community(pctrl, pin);
@@ -152,9 +161,8 @@ static bool intel_pad_owned_by_host(struct intel_pinctrl *pctrl, unsigned pin)
return true;
padno = pin_to_padno(community, pin);
- gpp = padno / NPADS_IN_GPP;
- gpp_offset = padno % NPADS_IN_GPP;
- offset = community->padown_offset + gpp * 16 + (gpp_offset / 8) * 4;
+ gpp = PADOWN_GPP(padno);
+ offset = community->padown_offset + gpp * 4;
padown = community->regs + offset;
return !(readl(padown) & PADOWN_MASK(padno));
@@ -163,7 +171,7 @@ static bool intel_pad_owned_by_host(struct intel_pinctrl *pctrl, unsigned pin)
static bool intel_pad_acpi_mode(struct intel_pinctrl *pctrl, unsigned pin)
{
const struct intel_community *community;
- unsigned padno, gpp, offset;
+ unsigned padno, gpp, offset, gpp_size;
void __iomem *hostown;
community = intel_get_community(pctrl, pin);
@@ -173,17 +181,18 @@ static bool intel_pad_acpi_mode(struct intel_pinctrl *pctrl, unsigned pin)
return false;
padno = pin_to_padno(community, pin);
- gpp = padno / NPADS_IN_GPP;
+ gpp_size = intel_npads_in_gpp(community);
+ gpp = padno / gpp_size;
offset = community->hostown_offset + gpp * 4;
hostown = community->regs + offset;
- return !(readl(hostown) & BIT(padno % NPADS_IN_GPP));
+ return !(readl(hostown) & BIT(padno % gpp_size));
}
static bool intel_pad_locked(struct intel_pinctrl *pctrl, unsigned pin)
{
struct intel_community *community;
- unsigned padno, gpp, offset;
+ unsigned padno, gpp, offset, gpp_size;
u32 value;
community = intel_get_community(pctrl, pin);
@@ -193,7 +202,8 @@ static bool intel_pad_locked(struct intel_pinctrl *pctrl, unsigned pin)
return false;
padno = pin_to_padno(community, pin);
- gpp = padno / NPADS_IN_GPP;
+ gpp_size = intel_npads_in_gpp(community);
+ gpp = padno / gpp_size;
/*
* If PADCFGLOCK and PADCFGLOCKTX bits are both clear for this pad,
@@ -202,12 +212,12 @@ static bool intel_pad_locked(struct intel_pinctrl *pctrl, unsigned pin)
*/
offset = community->padcfglock_offset + gpp * 8;
value = readl(community->regs + offset);
- if (value & BIT(pin % NPADS_IN_GPP))
+ if (value & BIT(pin % gpp_size))
return true;
offset = community->padcfglock_offset + 4 + gpp * 8;
value = readl(community->regs + offset);
- if (value & BIT(pin % NPADS_IN_GPP))
+ if (value & BIT(pin % gpp_size))
return true;
return false;
@@ -663,8 +673,9 @@ static void intel_gpio_irq_ack(struct irq_data *d)
community = intel_get_community(pctrl, pin);
if (community) {
unsigned padno = pin_to_padno(community, pin);
- unsigned gpp_offset = padno % NPADS_IN_GPP;
- unsigned gpp = padno / NPADS_IN_GPP;
+ unsigned gpp_size = intel_npads_in_gpp(community);
+ unsigned gpp_offset = padno % gpp_size;
+ unsigned gpp = padno / gpp_size;
writel(BIT(gpp_offset), community->regs + GPI_IS + gpp * 4);
}
@@ -685,8 +696,9 @@ static void intel_gpio_irq_mask_unmask(struct irq_data *d, bool mask)
community = intel_get_community(pctrl, pin);
if (community) {
unsigned padno = pin_to_padno(community, pin);
- unsigned gpp_offset = padno % NPADS_IN_GPP;
- unsigned gpp = padno / NPADS_IN_GPP;
+ unsigned gpp_size = intel_npads_in_gpp(community);
+ unsigned gpp_offset = padno % gpp_size;
+ unsigned gpp = padno / gpp_size;
void __iomem *reg;
u32 value;
@@ -772,7 +784,7 @@ static int intel_gpio_irq_wake(struct irq_data *d, unsigned int on)
struct intel_pinctrl *pctrl = gpiochip_to_pinctrl(gc);
const struct intel_community *community;
unsigned pin = irqd_to_hwirq(d);
- unsigned padno, gpp, gpp_offset;
+ unsigned padno, gpp, gpp_offset, gpp_size;
u32 gpe_en;
community = intel_get_community(pctrl, pin);
@@ -780,8 +792,9 @@ static int intel_gpio_irq_wake(struct irq_data *d, unsigned int on)
return -EINVAL;
padno = pin_to_padno(community, pin);
- gpp = padno / NPADS_IN_GPP;
- gpp_offset = padno % NPADS_IN_GPP;
+ gpp_size = intel_npads_in_gpp(community);
+ gpp = padno / gpp_size;
+ gpp_offset = padno % gpp_size;
/* Clear the existing wake status */
writel(BIT(gpp_offset), community->regs + GPI_GPE_STS + gpp * 4);
@@ -807,6 +820,7 @@ static irqreturn_t intel_gpio_community_irq_handler(struct intel_pinctrl *pctrl,
{
struct gpio_chip *gc = &pctrl->chip;
irqreturn_t ret = IRQ_NONE;
+ unsigned gpp_size = intel_npads_in_gpp(community);
int gpp;
for (gpp = 0; gpp < community->ngpps; gpp++) {
@@ -819,14 +833,14 @@ static irqreturn_t intel_gpio_community_irq_handler(struct intel_pinctrl *pctrl,
/* Only interrupts that are enabled */
pending &= enabled;
- for_each_set_bit(gpp_offset, &pending, NPADS_IN_GPP) {
+ for_each_set_bit(gpp_offset, &pending, gpp_size) {
unsigned padno, irq;
/*
* The last group in community can have less pins
* than NPADS_IN_GPP.
*/
- padno = gpp_offset + gpp * NPADS_IN_GPP;
+ padno = gpp_offset + gpp * gpp_size;
if (padno >= community->npins)
break;
@@ -1002,7 +1016,8 @@ int intel_pinctrl_probe(struct platform_device *pdev,
community->regs = regs;
community->pad_regs = regs + padbar;
- community->ngpps = DIV_ROUND_UP(community->npins, NPADS_IN_GPP);
+ community->ngpps = DIV_ROUND_UP(community->npins,
+ intel_npads_in_gpp(community));
}
irq = platform_get_irq(pdev, 0);
@@ -55,6 +55,8 @@ struct intel_function {
* ACPI).
* @ie_offset: Register offset of GPI_IE from @regs.
* @pin_base: Starting pin of pins in this community
+ * @gpp_size: Maximum number of pads in each group, such as PADCFGLOCK,
+ * HOSTSW_OWN, GPI_IS, GPI_IE, etc.
* @npins: Number of pins in this community
* @regs: Community specific common registers (reserved for core driver)
* @pad_regs: Community specific pad registers (reserved for core driver)
@@ -68,6 +70,7 @@ struct intel_community {
unsigned hostown_offset;
unsigned ie_offset;
unsigned pin_base;
+ unsigned gpp_size;
size_t npins;
void __iomem *regs;
void __iomem *pad_regs;