summaryrefslogtreecommitdiff
path: root/drivers/pinctrl/intel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-02-02 14:22:53 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2018-02-02 14:22:53 -0800
commitef991796be0e65b644fe60198bd1112830eff173 (patch)
treefcefb8bd7f8ba7d8dcde31ae37f703f05cb131a9 /drivers/pinctrl/intel
parentbf644990a796bd72d6f3977f3307169919a23f85 (diff)
parent02e389e63e3523828fc3832f27e0341885f60f6f (diff)
Merge tag 'pinctrl-v4.16-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl
Pull pin control updates from Linus Walleij: "This is the bulk of pin control changes for the v4.16 kernel cycle. Like with GPIO it is actually a bit calm this time. Core changes: - After lengthy discussions and partly due to my ignorance, we have merged a patch making pinctrl_force_default() and pinctrl_force_sleep() reprogram the states into the hardware of any hogged pins, even if they are already in the desired state. This only apply to hogged pins since groups of pins owned by drivers need to be managed by each driver, lest they could not do things like runtime PM and put pins to sleeping state even if the system as a whole is not in sleep. New drivers: - New driver for the Microsemi Ocelot SoC. This is used in ethernet switches. - The X-Powers AXP209 GPIO driver was extended to also deal with pin control and moved over from the GPIO subsystem. This circuit is a mixed-mode integrated circuit which is part of AllWinner designs. - New subdriver for the Qualcomm MSM8998 SoC, core of a high end mobile devices (phones) chipset. - New subdriver for the ST Microelectronics STM32MP157 MPU and STM32F769 MCU from the STM32 family. - New subdriver for the MediaTek MT7622 SoC. This is used for routers, repeater, gateways and such network infrastructure. - New subdriver for the NXP (former Freescale) i.MX 6ULL. This SoC has multimedia features and target "smart devices", I guess in-car entertainment, in-flight entertainment, industrial control panels etc. General improvements: - Incremental improvements on the SH-PFC subdrivers for things like the CAN bus. - Enable the glitch filter on Baytrail GPIOs used for interrupts. - Proper handling of pins to GPIO ranges on the Semtec SX150X - An IRQ setup ordering fix on MCP23S08. - A good set of janitorial coding style fixes" * tag 'pinctrl-v4.16-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: (102 commits) pinctrl: mcp23s08: fix irq setup order pinctrl: Forward declare struct device pinctrl: sunxi: Use of_clk_get_parent_count() instead of open coding pinctrl: stm32: add STM32F769 MCU support pinctrl: sx150x: Add a static gpio/pinctrl pin range mapping pinctrl: sx150x: Register pinctrl before adding the gpiochip pinctrl: sx150x: Unregister the pinctrl on release pinctrl: ingenic: Remove redundant dev_err call in ingenic_pinctrl_probe() pinctrl: sprd: Use seq_putc() in sprd_pinconf_group_dbg_show() pinctrl: pinmux: Use seq_putc() in pinmux_pins_show() pinctrl: abx500: Use seq_putc() in abx500_gpio_dbg_show() pinctrl: mediatek: mt7622: align error handling of mtk_hw_get_value call pinctrl: mediatek: mt7622: fix potential uninitialized value being returned pinctrl: uniphier: refactor drive strength get/set functions pinctrl: imx7ulp: constify struct imx_cfg_params_decode pinctrl: imx: constify struct imx_pinctrl_soc_info pinctrl: imx7d: simplify imx7d_pinctrl_probe pinctrl: imx: use struct imx_pinctrl_soc_info as a const pinctrl: sunxi-pinctrl: fix pin funtion can not be match correctly. pinctrl: qcom: Add msm8998 pinctrl driver ...
Diffstat (limited to 'drivers/pinctrl/intel')
-rw-r--r--drivers/pinctrl/intel/pinctrl-baytrail.c6
-rw-r--r--drivers/pinctrl/intel/pinctrl-cannonlake.c65
-rw-r--r--drivers/pinctrl/intel/pinctrl-cherryview.c59
-rw-r--r--drivers/pinctrl/intel/pinctrl-intel.c179
-rw-r--r--drivers/pinctrl/intel/pinctrl-intel.h3
-rw-r--r--drivers/pinctrl/intel/pinctrl-merrifield.c7
6 files changed, 202 insertions, 117 deletions
diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c
index 9c1ca29c60b7..6b52ea1440a6 100644
--- a/drivers/pinctrl/intel/pinctrl-baytrail.c
+++ b/drivers/pinctrl/intel/pinctrl-baytrail.c
@@ -46,6 +46,9 @@
#define BYT_TRIG_POS BIT(25)
#define BYT_TRIG_LVL BIT(24)
#define BYT_DEBOUNCE_EN BIT(20)
+#define BYT_GLITCH_FILTER_EN BIT(19)
+#define BYT_GLITCH_F_SLOW_CLK BIT(17)
+#define BYT_GLITCH_F_FAST_CLK BIT(16)
#define BYT_PULL_STR_SHIFT 9
#define BYT_PULL_STR_MASK (3 << BYT_PULL_STR_SHIFT)
#define BYT_PULL_STR_2K (0 << BYT_PULL_STR_SHIFT)
@@ -1579,6 +1582,9 @@ static int byt_irq_type(struct irq_data *d, unsigned int type)
*/
value &= ~(BYT_DIRECT_IRQ_EN | BYT_TRIG_POS | BYT_TRIG_NEG |
BYT_TRIG_LVL);
+ /* Enable glitch filtering */
+ value |= BYT_GLITCH_FILTER_EN | BYT_GLITCH_F_SLOW_CLK |
+ BYT_GLITCH_F_FAST_CLK;
writel(value, reg);
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[] = {
diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c
index 4471fd94e1fe..b1ae1618fefe 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);
}
diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c
index 12a1af45acb9..96e73e30204e 100644
--- a/drivers/pinctrl/intel/pinctrl-intel.c
+++ b/drivers/pinctrl/intel/pinctrl-intel.c
@@ -425,6 +425,18 @@ static void __intel_gpio_set_direction(void __iomem *padcfg0, bool input)
writel(value, padcfg0);
}
+static void intel_gpio_set_gpio_mode(void __iomem *padcfg0)
+{
+ u32 value;
+
+ /* Put the pad into GPIO mode */
+ value = readl(padcfg0) & ~PADCFG0_PMODE_MASK;
+ /* Disable SCI/SMI/NMI generation */
+ value &= ~(PADCFG0_GPIROUTIOXAPIC | PADCFG0_GPIROUTSCI);
+ value &= ~(PADCFG0_GPIROUTSMI | PADCFG0_GPIROUTNMI);
+ writel(value, padcfg0);
+}
+
static int intel_gpio_request_enable(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned pin)
@@ -432,7 +444,6 @@ static int intel_gpio_request_enable(struct pinctrl_dev *pctldev,
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
void __iomem *padcfg0;
unsigned long flags;
- u32 value;
raw_spin_lock_irqsave(&pctrl->lock, flags);
@@ -442,13 +453,7 @@ static int intel_gpio_request_enable(struct pinctrl_dev *pctldev,
}
padcfg0 = intel_get_padcfg(pctrl, pin, PADCFG0);
- /* Put the pad into GPIO mode */
- value = readl(padcfg0) & ~PADCFG0_PMODE_MASK;
- /* Disable SCI/SMI/NMI generation */
- value &= ~(PADCFG0_GPIROUTIOXAPIC | PADCFG0_GPIROUTSCI);
- value &= ~(PADCFG0_GPIROUTSMI | PADCFG0_GPIROUTNMI);
- writel(value, padcfg0);
-
+ intel_gpio_set_gpio_mode(padcfg0);
/* Disable TX buffer and enable RX (this will be input) */
__intel_gpio_set_direction(padcfg0, true);
@@ -806,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;
@@ -837,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;
@@ -870,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);
@@ -914,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;
@@ -935,6 +973,8 @@ static int intel_gpio_irq_type(struct irq_data *d, unsigned type)
raw_spin_lock_irqsave(&pctrl->lock, flags);
+ intel_gpio_set_gpio_mode(reg);
+
value = readl(reg);
value &= ~(PADCFG0_RXEVCFG_MASK | PADCFG0_RXINV);
@@ -969,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);
@@ -1000,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;
@@ -1044,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 = 0, 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;
@@ -1062,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;
+ }
}
/*
@@ -1126,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;
};
diff --git a/drivers/pinctrl/intel/pinctrl-merrifield.c b/drivers/pinctrl/intel/pinctrl-merrifield.c
index 86c4b3fab7b0..d9357054d41d 100644
--- a/drivers/pinctrl/intel/pinctrl-merrifield.c
+++ b/drivers/pinctrl/intel/pinctrl-merrifield.c
@@ -931,10 +931,17 @@ static int mrfld_pinctrl_probe(struct platform_device *pdev)
return 0;
}
+static const struct acpi_device_id mrfld_acpi_table[] = {
+ { "INTC1002" },
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, mrfld_acpi_table);
+
static struct platform_driver mrfld_pinctrl_driver = {
.probe = mrfld_pinctrl_probe,
.driver = {
.name = "pinctrl-merrifield",
+ .acpi_match_table = mrfld_acpi_table,
},
};