intel-pinctrl for v5.6-1

* Tiger Lake appears to have _HID enumeration, thus driver has been updated
 * Coffee Lake-S has the same IP as Sunrisepoint, thus ID has been added
 * Baytrail has got more clean ups and bug fixes, such as direct IRQ handling
 * Lynxpoint GPIO has been converted to true pin control driver
 * The common driver now uses IRQ chip enumeration via GPIO chip
 
 The following is an automated git shortlog grouped by driver:
 
 baytrail:
  -  Replace WARN with dev_info_once when setting direct-irq pin to output
  -  Do not clear IRQ flags on direct-irq enabled pins
  -  Reuse struct intel_pinctrl in the driver
  -  Use local variable to keep device pointer
  -  Keep pointer to struct device instead of its container
  -  Use GPIO direction definitions
  -  Move IRQ valid mask initialization to a dedicated callback
  -  Group GPIO IRQ chip initialization
  -  Allocate IRQ chip dynamic
 
 cherryview:
  -  Use GPIO direction definitions
 
 intel:
  -  Pass irqchip when adding gpiochip
  -  Add GPIO <-> pin mapping ranges via callback
  -  Share struct intel_pinctrl for wider use
  -  Use GPIO direction definitions
 
 lynxpoint:
  -  Update summary in the driver
  -  Switch to pin control API
  -  Add GPIO <-> pin mapping ranges via callback
  -  Implement ->pin_dbg_show()
  -  Add pin control operations
  -  Reuse struct intel_pinctrl in the driver
  -  Add pin control data structures
  -  Implement intel_gpio_get_direction callback
  -  Implement ->irq_ack() callback
  -  Move ownership check to IRQ chip
  -  Move lp_irq_type() closer to IRQ related routines
  -  Move ->remove closer to ->probe()
  -  Extract lp_gpio_acpi_use() for future use
  -  Convert unsigned to unsigned int
  -  Switch to memory mapped IO accessors
  -  Keep pointer to struct device instead of its container
  -  Relax GPIO request rules
  -  Assume 2 bits for mode selector
  -  Use standard pattern for memory allocation
  -  Use %pR to print IO resource
  -  Drop useless assignment
  -  Correct amount of pins
  -  Use raw_spinlock for locking
  -  Move GPIO driver to pin controller folder
 
 sunrisepoint:
  -  Add Coffee Lake-S ACPI ID
  -  Add missing Interrupt Status register offset
 
 tigerlake:
  -  Tiger Lake uses _HID enumeration
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEqaflIX74DDDzMJJtb7wzTHR8rCgFAl4lfB4ACgkQb7wzTHR8
 rCgy3g//VHTbsBk7+6NFXbI5iXgbU1sr9F9cIYbzawA3YLbR1Ioq9P89U3JPCeCz
 zaoxtd9HAxOxQrUFJGZKbsof6jS7Ee80mcvm0KQt2GNBmM4bZGS6qHofj5FAOxuz
 4MBjGINrlIntzG1RqjYxD+p2xuQ3p9H2yQIds9UTM1NB+hBIDLPx+3HUM2qbbf4s
 rbLQRc+kmVHoapmse6lV4lA2OyOW9BmgiTxeMaua/E6zyZ6WVNXLxXx+yXrEtUjj
 Q9M6moNZd4OP3pN/mGCyClLTMFyOcmaah6wdXy3GJRZ7/YD5+AnqbVTGsYLKy6To
 1w25Z6e6ygzbL8sqr5JwMiX9GnX6FeGEleY63zxvZ+WCC3TGWRzPWaTJuQIRToAz
 K3pdYWXOoK/J1fyzdjdkYHbqBbqjpB5oT/dWFx7Ii50kv41b8TEXPhDrWZSqvn9I
 J0KW/vICbsqPk8TBsQQ83nV6ILSTY5KakI8Qs5ngDov5oeKl0F/cLT9KqcY9nQdJ
 2mhJU5mn8cq4SvtyPD/NSRQHxX5xHx6Yi4KG2cXw0wJTZ+jP8rpl2di8ogDCFUK4
 fkQ/g+PhcPsW36kTKvLv57vhTqZ2u9rf9BcaJ7LGo9wsOjpGH6d4RCTiJ0VSn++T
 rkomWdFVgfMKmnsUwykyIV39mQzDy5e4vNO45wMs7LCimiRSkMA=
 =+ZAJ
 -----END PGP SIGNATURE-----

Merge tag 'intel-pinctrl-v5.6-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pinctrl/intel into devel

intel-pinctrl for v5.6-1

* Tiger Lake appears to have _HID enumeration, thus driver has been updated
* Coffee Lake-S has the same IP as Sunrisepoint, thus ID has been added
* Baytrail has got more clean ups and bug fixes, such as direct IRQ handling
* Lynxpoint GPIO has been converted to true pin control driver
* The common driver now uses IRQ chip enumeration via GPIO chip

The following is an automated git shortlog grouped by driver:

baytrail:
 -  Replace WARN with dev_info_once when setting direct-irq pin to output
 -  Do not clear IRQ flags on direct-irq enabled pins
 -  Reuse struct intel_pinctrl in the driver
 -  Use local variable to keep device pointer
 -  Keep pointer to struct device instead of its container
 -  Use GPIO direction definitions
 -  Move IRQ valid mask initialization to a dedicated callback
 -  Group GPIO IRQ chip initialization
 -  Allocate IRQ chip dynamic

cherryview:
 -  Use GPIO direction definitions

intel:
 -  Pass irqchip when adding gpiochip
 -  Add GPIO <-> pin mapping ranges via callback
 -  Share struct intel_pinctrl for wider use
 -  Use GPIO direction definitions

lynxpoint:
 -  Update summary in the driver
 -  Switch to pin control API
 -  Add GPIO <-> pin mapping ranges via callback
 -  Implement ->pin_dbg_show()
 -  Add pin control operations
 -  Reuse struct intel_pinctrl in the driver
 -  Add pin control data structures
 -  Implement intel_gpio_get_direction callback
 -  Implement ->irq_ack() callback
 -  Move ownership check to IRQ chip
 -  Move lp_irq_type() closer to IRQ related routines
 -  Move ->remove closer to ->probe()
 -  Extract lp_gpio_acpi_use() for future use
 -  Convert unsigned to unsigned int
 -  Switch to memory mapped IO accessors
 -  Keep pointer to struct device instead of its container
 -  Relax GPIO request rules
 -  Assume 2 bits for mode selector
 -  Use standard pattern for memory allocation
 -  Use %pR to print IO resource
 -  Drop useless assignment
 -  Correct amount of pins
 -  Use raw_spinlock for locking
 -  Move GPIO driver to pin controller folder

sunrisepoint:
 -  Add Coffee Lake-S ACPI ID
 -  Add missing Interrupt Status register offset

tigerlake:
 -  Tiger Lake uses _HID enumeration
This commit is contained in:
Linus Walleij 2020-01-23 15:44:29 +01:00
commit a1dd4bfb14
13 changed files with 1486 additions and 1008 deletions

View file

@ -8347,7 +8347,6 @@ S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/andy/linux-gpio-intel.git
F: drivers/gpio/gpio-ich.c
F: drivers/gpio/gpio-intel-mid.c
F: drivers/gpio/gpio-lynxpoint.c
F: drivers/gpio/gpio-merrifield.c
F: drivers/gpio/gpio-ml-ioh.c
F: drivers/gpio/gpio-pch.c

View file

@ -335,14 +335,6 @@ config GPIO_LPC32XX
Select this option to enable GPIO driver for
NXP LPC32XX devices.
config GPIO_LYNXPOINT
tristate "Intel Lynxpoint GPIO support"
depends on ACPI && X86
select GPIOLIB_IRQCHIP
help
driver for GPIO functionality on Intel Lynxpoint PCH chipset
Requires ACPI device enumeration code to set up a platform device.
config GPIO_MB86S7X
tristate "GPIO support for Fujitsu MB86S7x Platforms"
help

View file

@ -76,7 +76,6 @@ obj-$(CONFIG_GPIO_LP873X) += gpio-lp873x.o
obj-$(CONFIG_GPIO_LP87565) += gpio-lp87565.o
obj-$(CONFIG_GPIO_LPC18XX) += gpio-lpc18xx.o
obj-$(CONFIG_GPIO_LPC32XX) += gpio-lpc32xx.o
obj-$(CONFIG_GPIO_LYNXPOINT) += gpio-lynxpoint.o
obj-$(CONFIG_GPIO_MADERA) += gpio-madera.o
obj-$(CONFIG_GPIO_MAX3191X) += gpio-max3191x.o
obj-$(CONFIG_GPIO_MAX7300) += gpio-max7300.o

View file

@ -1,471 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* GPIO controller driver for Intel Lynxpoint PCH chipset>
* Copyright (c) 2012, Intel Corporation.
*
* Author: Mathias Nyman <mathias.nyman@linux.intel.com>
*/
#include <linux/acpi.h>
#include <linux/bitops.h>
#include <linux/gpio/driver.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/types.h>
/* LynxPoint chipset has support for 94 gpio pins */
#define LP_NUM_GPIO 94
/* Bitmapped register offsets */
#define LP_ACPI_OWNED 0x00 /* Bitmap, set by bios, 0: pin reserved for ACPI */
#define LP_GC 0x7C /* set APIC IRQ to IRQ14 or IRQ15 for all pins */
#define LP_INT_STAT 0x80
#define LP_INT_ENABLE 0x90
/* Each pin has two 32 bit config registers, starting at 0x100 */
#define LP_CONFIG1 0x100
#define LP_CONFIG2 0x104
/* LP_CONFIG1 reg bits */
#define OUT_LVL_BIT BIT(31)
#define IN_LVL_BIT BIT(30)
#define TRIG_SEL_BIT BIT(4) /* 0: Edge, 1: Level */
#define INT_INV_BIT BIT(3) /* Invert interrupt triggering */
#define DIR_BIT BIT(2) /* 0: Output, 1: Input */
#define USE_SEL_BIT BIT(0) /* 0: Native, 1: GPIO */
/* LP_CONFIG2 reg bits */
#define GPINDIS_BIT BIT(2) /* disable input sensing */
#define GPIWP_BIT (BIT(0) | BIT(1)) /* weak pull options */
struct lp_gpio {
struct gpio_chip chip;
struct platform_device *pdev;
spinlock_t lock;
unsigned long reg_base;
};
/*
* Lynxpoint gpios are controlled through both bitmapped registers and
* per gpio specific registers. The bitmapped registers are in chunks of
* 3 x 32bit registers to cover all 94 gpios
*
* per gpio specific registers consist of two 32bit registers per gpio
* (LP_CONFIG1 and LP_CONFIG2), with 94 gpios there's a total of
* 188 config registers.
*
* A simplified view of the register layout look like this:
*
* LP_ACPI_OWNED[31:0] gpio ownerships for gpios 0-31 (bitmapped registers)
* LP_ACPI_OWNED[63:32] gpio ownerships for gpios 32-63
* LP_ACPI_OWNED[94:64] gpio ownerships for gpios 63-94
* ...
* LP_INT_ENABLE[31:0] ...
* LP_INT_ENABLE[63:31] ...
* LP_INT_ENABLE[94:64] ...
* LP0_CONFIG1 (gpio 0) config1 reg for gpio 0 (per gpio registers)
* LP0_CONFIG2 (gpio 0) config2 reg for gpio 0
* LP1_CONFIG1 (gpio 1) config1 reg for gpio 1
* LP1_CONFIG2 (gpio 1) config2 reg for gpio 1
* LP2_CONFIG1 (gpio 2) ...
* LP2_CONFIG2 (gpio 2) ...
* ...
* LP94_CONFIG1 (gpio 94) ...
* LP94_CONFIG2 (gpio 94) ...
*/
static unsigned long lp_gpio_reg(struct gpio_chip *chip, unsigned offset,
int reg)
{
struct lp_gpio *lg = gpiochip_get_data(chip);
int reg_offset;
if (reg == LP_CONFIG1 || reg == LP_CONFIG2)
/* per gpio specific config registers */
reg_offset = offset * 8;
else
/* bitmapped registers */
reg_offset = (offset / 32) * 4;
return lg->reg_base + reg + reg_offset;
}
static int lp_gpio_request(struct gpio_chip *chip, unsigned offset)
{
struct lp_gpio *lg = gpiochip_get_data(chip);
unsigned long reg = lp_gpio_reg(chip, offset, LP_CONFIG1);
unsigned long conf2 = lp_gpio_reg(chip, offset, LP_CONFIG2);
unsigned long acpi_use = lp_gpio_reg(chip, offset, LP_ACPI_OWNED);
pm_runtime_get(&lg->pdev->dev); /* should we put if failed */
/* Fail if BIOS reserved pin for ACPI use */
if (!(inl(acpi_use) & BIT(offset % 32))) {
dev_err(&lg->pdev->dev, "gpio %d reserved for ACPI\n", offset);
return -EBUSY;
}
/* Fail if pin is in alternate function mode (not GPIO mode) */
if (!(inl(reg) & USE_SEL_BIT))
return -ENODEV;
/* enable input sensing */
outl(inl(conf2) & ~GPINDIS_BIT, conf2);
return 0;
}
static void lp_gpio_free(struct gpio_chip *chip, unsigned offset)
{
struct lp_gpio *lg = gpiochip_get_data(chip);
unsigned long conf2 = lp_gpio_reg(chip, offset, LP_CONFIG2);
/* disable input sensing */
outl(inl(conf2) | GPINDIS_BIT, conf2);
pm_runtime_put(&lg->pdev->dev);
}
static int lp_irq_type(struct irq_data *d, unsigned type)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct lp_gpio *lg = gpiochip_get_data(gc);
u32 hwirq = irqd_to_hwirq(d);
unsigned long flags;
u32 value;
unsigned long reg = lp_gpio_reg(&lg->chip, hwirq, LP_CONFIG1);
if (hwirq >= lg->chip.ngpio)
return -EINVAL;
spin_lock_irqsave(&lg->lock, flags);
value = inl(reg);
/* set both TRIG_SEL and INV bits to 0 for rising edge */
if (type & IRQ_TYPE_EDGE_RISING)
value &= ~(TRIG_SEL_BIT | INT_INV_BIT);
/* TRIG_SEL bit 0, INV bit 1 for falling edge */
if (type & IRQ_TYPE_EDGE_FALLING)
value = (value | INT_INV_BIT) & ~TRIG_SEL_BIT;
/* TRIG_SEL bit 1, INV bit 0 for level low */
if (type & IRQ_TYPE_LEVEL_LOW)
value = (value | TRIG_SEL_BIT) & ~INT_INV_BIT;
/* TRIG_SEL bit 1, INV bit 1 for level high */
if (type & IRQ_TYPE_LEVEL_HIGH)
value |= TRIG_SEL_BIT | INT_INV_BIT;
outl(value, reg);
if (type & IRQ_TYPE_EDGE_BOTH)
irq_set_handler_locked(d, handle_edge_irq);
else if (type & IRQ_TYPE_LEVEL_MASK)
irq_set_handler_locked(d, handle_level_irq);
spin_unlock_irqrestore(&lg->lock, flags);
return 0;
}
static int lp_gpio_get(struct gpio_chip *chip, unsigned offset)
{
unsigned long reg = lp_gpio_reg(chip, offset, LP_CONFIG1);
return !!(inl(reg) & IN_LVL_BIT);
}
static void lp_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
struct lp_gpio *lg = gpiochip_get_data(chip);
unsigned long reg = lp_gpio_reg(chip, offset, LP_CONFIG1);
unsigned long flags;
spin_lock_irqsave(&lg->lock, flags);
if (value)
outl(inl(reg) | OUT_LVL_BIT, reg);
else
outl(inl(reg) & ~OUT_LVL_BIT, reg);
spin_unlock_irqrestore(&lg->lock, flags);
}
static int lp_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
{
struct lp_gpio *lg = gpiochip_get_data(chip);
unsigned long reg = lp_gpio_reg(chip, offset, LP_CONFIG1);
unsigned long flags;
spin_lock_irqsave(&lg->lock, flags);
outl(inl(reg) | DIR_BIT, reg);
spin_unlock_irqrestore(&lg->lock, flags);
return 0;
}
static int lp_gpio_direction_output(struct gpio_chip *chip,
unsigned offset, int value)
{
struct lp_gpio *lg = gpiochip_get_data(chip);
unsigned long reg = lp_gpio_reg(chip, offset, LP_CONFIG1);
unsigned long flags;
lp_gpio_set(chip, offset, value);
spin_lock_irqsave(&lg->lock, flags);
outl(inl(reg) & ~DIR_BIT, reg);
spin_unlock_irqrestore(&lg->lock, flags);
return 0;
}
static void lp_gpio_irq_handler(struct irq_desc *desc)
{
struct irq_data *data = irq_desc_get_irq_data(desc);
struct gpio_chip *gc = irq_desc_get_handler_data(desc);
struct lp_gpio *lg = gpiochip_get_data(gc);
struct irq_chip *chip = irq_data_get_irq_chip(data);
unsigned long reg, ena, pending;
u32 base, pin;
/* check from GPIO controller which pin triggered the interrupt */
for (base = 0; base < lg->chip.ngpio; base += 32) {
reg = lp_gpio_reg(&lg->chip, base, LP_INT_STAT);
ena = lp_gpio_reg(&lg->chip, base, LP_INT_ENABLE);
/* Only interrupts that are enabled */
pending = inl(reg) & inl(ena);
for_each_set_bit(pin, &pending, 32) {
unsigned irq;
/* Clear before handling so we don't lose an edge */
outl(BIT(pin), reg);
irq = irq_find_mapping(lg->chip.irq.domain, base + pin);
generic_handle_irq(irq);
}
}
chip->irq_eoi(data);
}
static void lp_irq_unmask(struct irq_data *d)
{
}
static void lp_irq_mask(struct irq_data *d)
{
}
static void lp_irq_enable(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct lp_gpio *lg = gpiochip_get_data(gc);
u32 hwirq = irqd_to_hwirq(d);
unsigned long reg = lp_gpio_reg(&lg->chip, hwirq, LP_INT_ENABLE);
unsigned long flags;
spin_lock_irqsave(&lg->lock, flags);
outl(inl(reg) | BIT(hwirq % 32), reg);
spin_unlock_irqrestore(&lg->lock, flags);
}
static void lp_irq_disable(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct lp_gpio *lg = gpiochip_get_data(gc);
u32 hwirq = irqd_to_hwirq(d);
unsigned long reg = lp_gpio_reg(&lg->chip, hwirq, LP_INT_ENABLE);
unsigned long flags;
spin_lock_irqsave(&lg->lock, flags);
outl(inl(reg) & ~BIT(hwirq % 32), reg);
spin_unlock_irqrestore(&lg->lock, flags);
}
static struct irq_chip lp_irqchip = {
.name = "LP-GPIO",
.irq_mask = lp_irq_mask,
.irq_unmask = lp_irq_unmask,
.irq_enable = lp_irq_enable,
.irq_disable = lp_irq_disable,
.irq_set_type = lp_irq_type,
.flags = IRQCHIP_SKIP_SET_WAKE,
};
static int lp_gpio_irq_init_hw(struct gpio_chip *chip)
{
struct lp_gpio *lg = gpiochip_get_data(chip);
unsigned long reg;
unsigned base;
for (base = 0; base < lg->chip.ngpio; base += 32) {
/* disable gpio pin interrupts */
reg = lp_gpio_reg(&lg->chip, base, LP_INT_ENABLE);
outl(0, reg);
/* Clear interrupt status register */
reg = lp_gpio_reg(&lg->chip, base, LP_INT_STAT);
outl(0xffffffff, reg);
}
return 0;
}
static int lp_gpio_probe(struct platform_device *pdev)
{
struct lp_gpio *lg;
struct gpio_chip *gc;
struct resource *io_rc, *irq_rc;
struct device *dev = &pdev->dev;
unsigned long reg_len;
int ret = -ENODEV;
lg = devm_kzalloc(dev, sizeof(struct lp_gpio), GFP_KERNEL);
if (!lg)
return -ENOMEM;
lg->pdev = pdev;
platform_set_drvdata(pdev, lg);
io_rc = platform_get_resource(pdev, IORESOURCE_IO, 0);
irq_rc = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!io_rc) {
dev_err(dev, "missing IO resources\n");
return -EINVAL;
}
lg->reg_base = io_rc->start;
reg_len = resource_size(io_rc);
if (!devm_request_region(dev, lg->reg_base, reg_len, "lp-gpio")) {
dev_err(dev, "failed requesting IO region 0x%x\n",
(unsigned int)lg->reg_base);
return -EBUSY;
}
spin_lock_init(&lg->lock);
gc = &lg->chip;
gc->label = dev_name(dev);
gc->owner = THIS_MODULE;
gc->request = lp_gpio_request;
gc->free = lp_gpio_free;
gc->direction_input = lp_gpio_direction_input;
gc->direction_output = lp_gpio_direction_output;
gc->get = lp_gpio_get;
gc->set = lp_gpio_set;
gc->base = -1;
gc->ngpio = LP_NUM_GPIO;
gc->can_sleep = false;
gc->parent = dev;
/* set up interrupts */
if (irq_rc && irq_rc->start) {
struct gpio_irq_chip *girq;
girq = &gc->irq;
girq->chip = &lp_irqchip;
girq->init_hw = lp_gpio_irq_init_hw;
girq->parent_handler = lp_gpio_irq_handler;
girq->num_parents = 1;
girq->parents = devm_kcalloc(&pdev->dev, girq->num_parents,
sizeof(*girq->parents),
GFP_KERNEL);
if (!girq->parents)
return -ENOMEM;
girq->parents[0] = (unsigned)irq_rc->start;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_bad_irq;
}
ret = devm_gpiochip_add_data(dev, gc, lg);
if (ret) {
dev_err(dev, "failed adding lp-gpio chip\n");
return ret;
}
pm_runtime_enable(dev);
return 0;
}
static int lp_gpio_runtime_suspend(struct device *dev)
{
return 0;
}
static int lp_gpio_runtime_resume(struct device *dev)
{
return 0;
}
static int lp_gpio_resume(struct device *dev)
{
struct lp_gpio *lg = dev_get_drvdata(dev);
unsigned long reg;
int i;
/* on some hardware suspend clears input sensing, re-enable it here */
for (i = 0; i < lg->chip.ngpio; i++) {
if (gpiochip_is_requested(&lg->chip, i) != NULL) {
reg = lp_gpio_reg(&lg->chip, i, LP_CONFIG2);
outl(inl(reg) & ~GPINDIS_BIT, reg);
}
}
return 0;
}
static const struct dev_pm_ops lp_gpio_pm_ops = {
.runtime_suspend = lp_gpio_runtime_suspend,
.runtime_resume = lp_gpio_runtime_resume,
.resume = lp_gpio_resume,
};
static const struct acpi_device_id lynxpoint_gpio_acpi_match[] = {
{ "INT33C7", 0 },
{ "INT3437", 0 },
{ }
};
MODULE_DEVICE_TABLE(acpi, lynxpoint_gpio_acpi_match);
static int lp_gpio_remove(struct platform_device *pdev)
{
pm_runtime_disable(&pdev->dev);
return 0;
}
static struct platform_driver lp_gpio_driver = {
.probe = lp_gpio_probe,
.remove = lp_gpio_remove,
.driver = {
.name = "lp_gpio",
.pm = &lp_gpio_pm_ops,
.acpi_match_table = ACPI_PTR(lynxpoint_gpio_acpi_match),
},
};
static int __init lp_gpio_init(void)
{
return platform_driver_register(&lp_gpio_driver);
}
static void __exit lp_gpio_exit(void)
{
platform_driver_unregister(&lp_gpio_driver);
}
subsys_initcall(lp_gpio_init);
module_exit(lp_gpio_exit);
MODULE_AUTHOR("Mathias Nyman (Intel)");
MODULE_DESCRIPTION("GPIO interface for Intel Lynxpoint");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:lp_gpio");

View file

@ -31,6 +31,19 @@ config PINCTRL_CHERRYVIEW
Cherryview/Braswell pinctrl driver provides an interface that
allows configuring of SoC pins and using them as GPIOs.
config PINCTRL_LYNXPOINT
tristate "Intel Lynxpoint pinctrl and GPIO driver"
depends on ACPI
select PINMUX
select PINCONF
select GENERIC_PINCONF
select GPIOLIB
select GPIOLIB_IRQCHIP
help
Lynxpoint is the PCH of Intel Haswell. This pinctrl driver
provides an interface that allows configuring of PCH pins and
using them as GPIOs.
config PINCTRL_MERRIFIELD
tristate "Intel Merrifield pinctrl driver"
depends on X86_INTEL_MID

View file

@ -3,6 +3,7 @@
obj-$(CONFIG_PINCTRL_BAYTRAIL) += pinctrl-baytrail.o
obj-$(CONFIG_PINCTRL_CHERRYVIEW) += pinctrl-cherryview.o
obj-$(CONFIG_PINCTRL_LYNXPOINT) += pinctrl-lynxpoint.o
obj-$(CONFIG_PINCTRL_MERRIFIELD) += pinctrl-merrifield.o
obj-$(CONFIG_PINCTRL_INTEL) += pinctrl-intel.o
obj-$(CONFIG_PINCTRL_BROXTON) += pinctrl-broxton.o

View file

@ -93,7 +93,7 @@
#define BYT_DEFAULT_GPIO_MUX 0
#define BYT_ALTER_GPIO_MUX 1
struct byt_gpio_pin_context {
struct intel_pad_context {
u32 conf0;
u32 val;
};
@ -105,16 +105,6 @@ struct byt_gpio_pin_context {
.pad_map = (map),\
}
struct byt_gpio {
struct gpio_chip chip;
struct platform_device *pdev;
struct pinctrl_dev *pctl_dev;
struct pinctrl_desc pctl_desc;
const struct intel_pinctrl_soc_data *soc_data;
struct intel_community *communities_copy;
struct byt_gpio_pin_context *saved_context;
};
/* SCORE pins, aka GPIOC_<pin_no> or GPIO_S0_SC[<pin_no>] */
static const struct pinctrl_pin_desc byt_score_pins[] = {
PINCTRL_PIN(0, "SATA_GP0"),
@ -550,14 +540,14 @@ static const struct intel_pinctrl_soc_data *byt_soc_data[] = {
static DEFINE_RAW_SPINLOCK(byt_lock);
static struct intel_community *byt_get_community(struct byt_gpio *vg,
static struct intel_community *byt_get_community(struct intel_pinctrl *vg,
unsigned int pin)
{
struct intel_community *comm;
int i;
for (i = 0; i < vg->soc_data->ncommunities; i++) {
comm = vg->communities_copy + i;
for (i = 0; i < vg->ncommunities; i++) {
comm = vg->communities + i;
if (pin < comm->pin_base + comm->npins && pin >= comm->pin_base)
return comm;
}
@ -565,7 +555,7 @@ static struct intel_community *byt_get_community(struct byt_gpio *vg,
return NULL;
}
static void __iomem *byt_gpio_reg(struct byt_gpio *vg, unsigned int offset,
static void __iomem *byt_gpio_reg(struct intel_pinctrl *vg, unsigned int offset,
int reg)
{
struct intel_community *comm = byt_get_community(vg, offset);
@ -592,17 +582,17 @@ static void __iomem *byt_gpio_reg(struct byt_gpio *vg, unsigned int offset,
static int byt_get_groups_count(struct pinctrl_dev *pctldev)
{
struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctldev);
return vg->soc_data->ngroups;
return vg->soc->ngroups;
}
static const char *byt_get_group_name(struct pinctrl_dev *pctldev,
unsigned int selector)
{
struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctldev);
return vg->soc_data->groups[selector].name;
return vg->soc->groups[selector].name;
}
static int byt_get_group_pins(struct pinctrl_dev *pctldev,
@ -610,10 +600,10 @@ static int byt_get_group_pins(struct pinctrl_dev *pctldev,
const unsigned int **pins,
unsigned int *num_pins)
{
struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctldev);
*pins = vg->soc_data->groups[selector].pins;
*num_pins = vg->soc_data->groups[selector].npins;
*pins = vg->soc->groups[selector].pins;
*num_pins = vg->soc->groups[selector].npins;
return 0;
}
@ -626,17 +616,17 @@ static const struct pinctrl_ops byt_pinctrl_ops = {
static int byt_get_functions_count(struct pinctrl_dev *pctldev)
{
struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctldev);
return vg->soc_data->nfunctions;
return vg->soc->nfunctions;
}
static const char *byt_get_function_name(struct pinctrl_dev *pctldev,
unsigned int selector)
{
struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctldev);
return vg->soc_data->functions[selector].name;
return vg->soc->functions[selector].name;
}
static int byt_get_function_groups(struct pinctrl_dev *pctldev,
@ -644,15 +634,15 @@ static int byt_get_function_groups(struct pinctrl_dev *pctldev,
const char * const **groups,
unsigned int *num_groups)
{
struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctldev);
*groups = vg->soc_data->functions[selector].groups;
*num_groups = vg->soc_data->functions[selector].ngroups;
*groups = vg->soc->functions[selector].groups;
*num_groups = vg->soc->functions[selector].ngroups;
return 0;
}
static void byt_set_group_simple_mux(struct byt_gpio *vg,
static void byt_set_group_simple_mux(struct intel_pinctrl *vg,
const struct intel_pingroup group,
unsigned int func)
{
@ -667,7 +657,7 @@ static void byt_set_group_simple_mux(struct byt_gpio *vg,
padcfg0 = byt_gpio_reg(vg, group.pins[i], BYT_CONF0_REG);
if (!padcfg0) {
dev_warn(&vg->pdev->dev,
dev_warn(vg->dev,
"Group %s, pin %i not muxed (no padcfg0)\n",
group.name, i);
continue;
@ -682,7 +672,7 @@ static void byt_set_group_simple_mux(struct byt_gpio *vg,
raw_spin_unlock_irqrestore(&byt_lock, flags);
}
static void byt_set_group_mixed_mux(struct byt_gpio *vg,
static void byt_set_group_mixed_mux(struct intel_pinctrl *vg,
const struct intel_pingroup group,
const unsigned int *func)
{
@ -697,7 +687,7 @@ static void byt_set_group_mixed_mux(struct byt_gpio *vg,
padcfg0 = byt_gpio_reg(vg, group.pins[i], BYT_CONF0_REG);
if (!padcfg0) {
dev_warn(&vg->pdev->dev,
dev_warn(vg->dev,
"Group %s, pin %i not muxed (no padcfg0)\n",
group.name, i);
continue;
@ -715,9 +705,9 @@ static void byt_set_group_mixed_mux(struct byt_gpio *vg,
static int byt_set_mux(struct pinctrl_dev *pctldev, unsigned int func_selector,
unsigned int group_selector)
{
struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
const struct intel_function func = vg->soc_data->functions[func_selector];
const struct intel_pingroup group = vg->soc_data->groups[group_selector];
struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctldev);
const struct intel_function func = vg->soc->functions[func_selector];
const struct intel_pingroup group = vg->soc->groups[group_selector];
if (group.modes)
byt_set_group_mixed_mux(vg, group, group.modes);
@ -729,22 +719,22 @@ static int byt_set_mux(struct pinctrl_dev *pctldev, unsigned int func_selector,
return 0;
}
static u32 byt_get_gpio_mux(struct byt_gpio *vg, unsigned int offset)
static u32 byt_get_gpio_mux(struct intel_pinctrl *vg, unsigned int offset)
{
/* SCORE pin 92-93 */
if (!strcmp(vg->soc_data->uid, BYT_SCORE_ACPI_UID) &&
if (!strcmp(vg->soc->uid, BYT_SCORE_ACPI_UID) &&
offset >= 92 && offset <= 93)
return BYT_ALTER_GPIO_MUX;
/* SUS pin 11-21 */
if (!strcmp(vg->soc_data->uid, BYT_SUS_ACPI_UID) &&
if (!strcmp(vg->soc->uid, BYT_SUS_ACPI_UID) &&
offset >= 11 && offset <= 21)
return BYT_ALTER_GPIO_MUX;
return BYT_DEFAULT_GPIO_MUX;
}
static void byt_gpio_clear_triggering(struct byt_gpio *vg, unsigned int offset)
static void byt_gpio_clear_triggering(struct intel_pinctrl *vg, unsigned int offset)
{
void __iomem *reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
unsigned long flags;
@ -752,7 +742,13 @@ static void byt_gpio_clear_triggering(struct byt_gpio *vg, unsigned int offset)
raw_spin_lock_irqsave(&byt_lock, flags);
value = readl(reg);
value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
/* Do not clear direct-irq enabled IRQs (from gpio_disable_free) */
if (value & BYT_DIRECT_IRQ_EN)
/* nothing to do */ ;
else
value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
writel(value, reg);
raw_spin_unlock_irqrestore(&byt_lock, flags);
}
@ -761,7 +757,7 @@ static int byt_gpio_request_enable(struct pinctrl_dev *pctl_dev,
struct pinctrl_gpio_range *range,
unsigned int offset)
{
struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev);
struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctl_dev);
void __iomem *reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
u32 value, gpio_mux;
unsigned long flags;
@ -784,13 +780,12 @@ static int byt_gpio_request_enable(struct pinctrl_dev *pctl_dev,
value |= gpio_mux;
writel(value, reg);
dev_warn(&vg->pdev->dev, FW_BUG
"pin %u forcibly re-configured as GPIO\n", offset);
dev_warn(vg->dev, FW_BUG "pin %u forcibly re-configured as GPIO\n", offset);
}
raw_spin_unlock_irqrestore(&byt_lock, flags);
pm_runtime_get(&vg->pdev->dev);
pm_runtime_get(vg->dev);
return 0;
}
@ -799,10 +794,10 @@ static void byt_gpio_disable_free(struct pinctrl_dev *pctl_dev,
struct pinctrl_gpio_range *range,
unsigned int offset)
{
struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev);
struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctl_dev);
byt_gpio_clear_triggering(vg, offset);
pm_runtime_put(&vg->pdev->dev);
pm_runtime_put(vg->dev);
}
static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev,
@ -810,7 +805,7 @@ static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev,
unsigned int offset,
bool input)
{
struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev);
struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctl_dev);
void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
unsigned long flags;
@ -822,15 +817,15 @@ static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev,
value &= ~BYT_DIR_MASK;
if (input)
value |= BYT_OUTPUT_EN;
else
else if (readl(conf_reg) & BYT_DIRECT_IRQ_EN)
/*
* Before making any direction modifications, do a check if gpio
* is set for direct IRQ. On baytrail, setting GPIO to output
* does not make sense, so let's at least warn the caller before
* does not make sense, so let's at least inform the caller before
* they shoot themselves in the foot.
*/
WARN(readl(conf_reg) & BYT_DIRECT_IRQ_EN,
"Potential Error: Setting GPIO with direct_irq_en to output");
dev_info_once(vg->dev, "Potential Error: Setting GPIO with direct_irq_en to output");
writel(value, val_reg);
raw_spin_unlock_irqrestore(&byt_lock, flags);
@ -893,7 +888,7 @@ static int byt_set_pull_strength(u32 *reg, u16 strength)
static int byt_pin_config_get(struct pinctrl_dev *pctl_dev, unsigned int offset,
unsigned long *config)
{
struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev);
struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctl_dev);
enum pin_config_param param = pinconf_to_config_param(*config);
void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
@ -978,7 +973,7 @@ static int byt_pin_config_set(struct pinctrl_dev *pctl_dev,
unsigned long *configs,
unsigned int num_configs)
{
struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev);
struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctl_dev);
unsigned int param, arg;
void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
@ -1012,7 +1007,7 @@ static int byt_pin_config_set(struct pinctrl_dev *pctl_dev,
if (val & BYT_INPUT_EN) {
val &= ~BYT_INPUT_EN;
writel(val, val_reg);
dev_warn(&vg->pdev->dev,
dev_warn(vg->dev,
"pin %u forcibly set to input mode\n",
offset);
}
@ -1034,7 +1029,7 @@ static int byt_pin_config_set(struct pinctrl_dev *pctl_dev,
if (val & BYT_INPUT_EN) {
val &= ~BYT_INPUT_EN;
writel(val, val_reg);
dev_warn(&vg->pdev->dev,
dev_warn(vg->dev,
"pin %u forcibly set to input mode\n",
offset);
}
@ -1115,7 +1110,7 @@ static const struct pinctrl_desc byt_pinctrl_desc = {
static int byt_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
struct byt_gpio *vg = gpiochip_get_data(chip);
struct intel_pinctrl *vg = gpiochip_get_data(chip);
void __iomem *reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
unsigned long flags;
u32 val;
@ -1129,7 +1124,7 @@ static int byt_gpio_get(struct gpio_chip *chip, unsigned int offset)
static void byt_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
{
struct byt_gpio *vg = gpiochip_get_data(chip);
struct intel_pinctrl *vg = gpiochip_get_data(chip);
void __iomem *reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
unsigned long flags;
u32 old_val;
@ -1148,7 +1143,7 @@ static void byt_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
static int byt_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
{
struct byt_gpio *vg = gpiochip_get_data(chip);
struct intel_pinctrl *vg = gpiochip_get_data(chip);
void __iomem *reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
unsigned long flags;
u32 value;
@ -1161,9 +1156,9 @@ static int byt_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
raw_spin_unlock_irqrestore(&byt_lock, flags);
if (!(value & BYT_OUTPUT_EN))
return 0;
return GPIO_LINE_DIRECTION_OUT;
if (!(value & BYT_INPUT_EN))
return 1;
return GPIO_LINE_DIRECTION_IN;
return -EINVAL;
}
@ -1188,11 +1183,11 @@ static int byt_gpio_direction_output(struct gpio_chip *chip,
static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
{
struct byt_gpio *vg = gpiochip_get_data(chip);
struct intel_pinctrl *vg = gpiochip_get_data(chip);
int i;
u32 conf0, val;
for (i = 0; i < vg->soc_data->npins; i++) {
for (i = 0; i < vg->soc->npins; i++) {
const struct intel_community *comm;
const char *pull_str = NULL;
const char *pull = NULL;
@ -1202,7 +1197,7 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
unsigned int pin;
raw_spin_lock_irqsave(&byt_lock, flags);
pin = vg->soc_data->pins[i].number;
pin = vg->soc->pins[i].number;
reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
if (!reg) {
seq_printf(s,
@ -1297,7 +1292,7 @@ static const struct gpio_chip byt_gpio_chip = {
static void byt_irq_ack(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct byt_gpio *vg = gpiochip_get_data(gc);
struct intel_pinctrl *vg = gpiochip_get_data(gc);
unsigned int offset = irqd_to_hwirq(d);
void __iomem *reg;
@ -1313,7 +1308,7 @@ static void byt_irq_ack(struct irq_data *d)
static void byt_irq_mask(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct byt_gpio *vg = gpiochip_get_data(gc);
struct intel_pinctrl *vg = gpiochip_get_data(gc);
byt_gpio_clear_triggering(vg, irqd_to_hwirq(d));
}
@ -1321,7 +1316,7 @@ static void byt_irq_mask(struct irq_data *d)
static void byt_irq_unmask(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct byt_gpio *vg = gpiochip_get_data(gc);
struct intel_pinctrl *vg = gpiochip_get_data(gc);
unsigned int offset = irqd_to_hwirq(d);
unsigned long flags;
void __iomem *reg;
@ -1359,7 +1354,7 @@ static void byt_irq_unmask(struct irq_data *d)
static int byt_irq_type(struct irq_data *d, unsigned int type)
{
struct byt_gpio *vg = gpiochip_get_data(irq_data_get_irq_chip_data(d));
struct intel_pinctrl *vg = gpiochip_get_data(irq_data_get_irq_chip_data(d));
u32 offset = irqd_to_hwirq(d);
u32 value;
unsigned long flags;
@ -1395,20 +1390,10 @@ static int byt_irq_type(struct irq_data *d, unsigned int type)
return 0;
}
static struct irq_chip byt_irqchip = {
.name = "BYT-GPIO",
.irq_ack = byt_irq_ack,
.irq_mask = byt_irq_mask,
.irq_unmask = byt_irq_unmask,
.irq_set_type = byt_irq_type,
.flags = IRQCHIP_SKIP_SET_WAKE,
};
static void byt_gpio_irq_handler(struct irq_desc *desc)
{
struct irq_data *data = irq_desc_get_irq_data(desc);
struct byt_gpio *vg = gpiochip_get_data(
irq_desc_get_handler_data(desc));
struct intel_pinctrl *vg = gpiochip_get_data(irq_desc_get_handler_data(desc));
struct irq_chip *chip = irq_data_get_irq_chip(data);
u32 base, pin;
void __iomem *reg;
@ -1420,7 +1405,7 @@ static void byt_gpio_irq_handler(struct irq_desc *desc)
reg = byt_gpio_reg(vg, base, BYT_INT_STAT_REG);
if (!reg) {
dev_warn(&vg->pdev->dev,
dev_warn(vg->dev,
"Pin %i: could not retrieve interrupt status register\n",
base);
continue;
@ -1441,22 +1426,9 @@ static void byt_init_irq_valid_mask(struct gpio_chip *chip,
unsigned long *valid_mask,
unsigned int ngpios)
{
/*
* FIXME: currently the valid_mask is filled in as part of
* initializing the irq_chip below in byt_gpio_irq_init_hw().
* when converting this driver to the new way of passing the
* gpio_irq_chip along when adding the gpio_chip, move the
* mask initialization into this callback instead. Right now
* this callback is here to make sure the mask gets allocated.
*/
}
static int byt_gpio_irq_init_hw(struct gpio_chip *chip)
{
struct byt_gpio *vg = gpiochip_get_data(chip);
struct device *dev = &vg->pdev->dev;
struct intel_pinctrl *vg = gpiochip_get_data(chip);
void __iomem *reg;
u32 base, value;
u32 value;
int i;
/*
@ -1464,12 +1436,12 @@ static int byt_gpio_irq_init_hw(struct gpio_chip *chip)
* do not use direct IRQ mode. This will prevent spurious
* interrupts from misconfigured pins.
*/
for (i = 0; i < vg->soc_data->npins; i++) {
unsigned int pin = vg->soc_data->pins[i].number;
for (i = 0; i < vg->soc->npins; i++) {
unsigned int pin = vg->soc->pins[i].number;
reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
if (!reg) {
dev_warn(&vg->pdev->dev,
dev_warn(vg->dev,
"Pin %i: could not retrieve conf0 register\n",
i);
continue;
@ -1477,20 +1449,27 @@ static int byt_gpio_irq_init_hw(struct gpio_chip *chip)
value = readl(reg);
if (value & BYT_DIRECT_IRQ_EN) {
clear_bit(i, chip->irq.valid_mask);
dev_dbg(dev, "excluding GPIO %d from IRQ domain\n", i);
clear_bit(i, valid_mask);
dev_dbg(vg->dev, "excluding GPIO %d from IRQ domain\n", i);
} else if ((value & BYT_PIN_MUX) == byt_get_gpio_mux(vg, i)) {
byt_gpio_clear_triggering(vg, i);
dev_dbg(dev, "disabling GPIO %d\n", i);
dev_dbg(vg->dev, "disabling GPIO %d\n", i);
}
}
}
static int byt_gpio_irq_init_hw(struct gpio_chip *chip)
{
struct intel_pinctrl *vg = gpiochip_get_data(chip);
void __iomem *reg;
u32 base, value;
/* clear interrupt status trigger registers */
for (base = 0; base < vg->soc_data->npins; base += 32) {
for (base = 0; base < vg->soc->npins; base += 32) {
reg = byt_gpio_reg(vg, base, BYT_INT_STAT_REG);
if (!reg) {
dev_warn(&vg->pdev->dev,
dev_warn(vg->dev,
"Pin %i: could not retrieve irq status reg\n",
base);
continue;
@ -1501,7 +1480,7 @@ static int byt_gpio_irq_init_hw(struct gpio_chip *chip)
might be misconfigured in bios */
value = readl(reg);
if (value)
dev_err(&vg->pdev->dev,
dev_err(vg->dev,
"GPIO interrupt error, pins misconfigured. INT_STAT%u: 0x%08x\n",
base / 32, value);
}
@ -1511,19 +1490,20 @@ static int byt_gpio_irq_init_hw(struct gpio_chip *chip)
static int byt_gpio_add_pin_ranges(struct gpio_chip *chip)
{
struct byt_gpio *vg = gpiochip_get_data(chip);
struct device *dev = &vg->pdev->dev;
struct intel_pinctrl *vg = gpiochip_get_data(chip);
struct device *dev = vg->dev;
int ret;
ret = gpiochip_add_pin_range(chip, dev_name(dev), 0, 0, vg->soc_data->npins);
ret = gpiochip_add_pin_range(chip, dev_name(dev), 0, 0, vg->soc->npins);
if (ret)
dev_err(dev, "failed to add GPIO pin range\n");
return ret;
}
static int byt_gpio_probe(struct byt_gpio *vg)
static int byt_gpio_probe(struct intel_pinctrl *vg)
{
struct platform_device *pdev = to_platform_device(vg->dev);
struct gpio_chip *gc;
struct resource *irq_rc;
int ret;
@ -1531,32 +1511,39 @@ static int byt_gpio_probe(struct byt_gpio *vg)
/* Set up gpio chip */
vg->chip = byt_gpio_chip;
gc = &vg->chip;
gc->label = dev_name(&vg->pdev->dev);
gc->label = dev_name(vg->dev);
gc->base = -1;
gc->can_sleep = false;
gc->add_pin_ranges = byt_gpio_add_pin_ranges;
gc->parent = &vg->pdev->dev;
gc->ngpio = vg->soc_data->npins;
gc->irq.init_valid_mask = byt_init_irq_valid_mask;
gc->parent = vg->dev;
gc->ngpio = vg->soc->npins;
#ifdef CONFIG_PM_SLEEP
vg->saved_context = devm_kcalloc(&vg->pdev->dev, gc->ngpio,
sizeof(*vg->saved_context), GFP_KERNEL);
if (!vg->saved_context)
vg->context.pads = devm_kcalloc(vg->dev, gc->ngpio, sizeof(*vg->context.pads),
GFP_KERNEL);
if (!vg->context.pads)
return -ENOMEM;
#endif
/* set up interrupts */
irq_rc = platform_get_resource(vg->pdev, IORESOURCE_IRQ, 0);
irq_rc = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (irq_rc && irq_rc->start) {
struct gpio_irq_chip *girq;
vg->irqchip.name = "BYT-GPIO",
vg->irqchip.irq_ack = byt_irq_ack,
vg->irqchip.irq_mask = byt_irq_mask,
vg->irqchip.irq_unmask = byt_irq_unmask,
vg->irqchip.irq_set_type = byt_irq_type,
vg->irqchip.flags = IRQCHIP_SKIP_SET_WAKE,
girq = &gc->irq;
girq->chip = &byt_irqchip;
girq->chip = &vg->irqchip;
girq->init_hw = byt_gpio_irq_init_hw;
girq->init_valid_mask = byt_init_irq_valid_mask;
girq->parent_handler = byt_gpio_irq_handler;
girq->num_parents = 1;
girq->parents = devm_kcalloc(&vg->pdev->dev, girq->num_parents,
girq->parents = devm_kcalloc(vg->dev, girq->num_parents,
sizeof(*girq->parents), GFP_KERNEL);
if (!girq->parents)
return -ENOMEM;
@ -1565,34 +1552,35 @@ static int byt_gpio_probe(struct byt_gpio *vg)
girq->handler = handle_bad_irq;
}
ret = devm_gpiochip_add_data(&vg->pdev->dev, gc, vg);
ret = devm_gpiochip_add_data(vg->dev, gc, vg);
if (ret) {
dev_err(&vg->pdev->dev, "failed adding byt-gpio chip\n");
dev_err(vg->dev, "failed adding byt-gpio chip\n");
return ret;
}
return ret;
}
static int byt_set_soc_data(struct byt_gpio *vg,
const struct intel_pinctrl_soc_data *soc_data)
static int byt_set_soc_data(struct intel_pinctrl *vg,
const struct intel_pinctrl_soc_data *soc)
{
struct platform_device *pdev = to_platform_device(vg->dev);
int i;
vg->soc_data = soc_data;
vg->communities_copy = devm_kcalloc(&vg->pdev->dev,
soc_data->ncommunities,
sizeof(*vg->communities_copy),
GFP_KERNEL);
if (!vg->communities_copy)
vg->soc = soc;
vg->ncommunities = vg->soc->ncommunities;
vg->communities = devm_kcalloc(vg->dev, vg->ncommunities,
sizeof(*vg->communities), GFP_KERNEL);
if (!vg->communities)
return -ENOMEM;
for (i = 0; i < soc_data->ncommunities; i++) {
struct intel_community *comm = vg->communities_copy + i;
for (i = 0; i < vg->soc->ncommunities; i++) {
struct intel_community *comm = vg->communities + i;
*comm = vg->soc_data->communities[i];
*comm = vg->soc->communities[i];
comm->pad_regs = devm_platform_ioremap_resource(vg->pdev, 0);
comm->pad_regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(comm->pad_regs))
return PTR_ERR(comm->pad_regs);
}
@ -1610,15 +1598,16 @@ static int byt_pinctrl_probe(struct platform_device *pdev)
{
const struct intel_pinctrl_soc_data *soc_data = NULL;
const struct intel_pinctrl_soc_data **soc_table;
struct device *dev = &pdev->dev;
struct acpi_device *acpi_dev;
struct byt_gpio *vg;
struct intel_pinctrl *vg;
int i, ret;
acpi_dev = ACPI_COMPANION(&pdev->dev);
acpi_dev = ACPI_COMPANION(dev);
if (!acpi_dev)
return -ENODEV;
soc_table = (const struct intel_pinctrl_soc_data **)device_get_match_data(&pdev->dev);
soc_table = (const struct intel_pinctrl_soc_data **)device_get_match_data(dev);
for (i = 0; soc_table[i]; i++) {
if (!strcmp(acpi_dev->pnp.unique_id, soc_table[i]->uid)) {
@ -1630,26 +1619,26 @@ static int byt_pinctrl_probe(struct platform_device *pdev)
if (!soc_data)
return -ENODEV;
vg = devm_kzalloc(&pdev->dev, sizeof(*vg), GFP_KERNEL);
vg = devm_kzalloc(dev, sizeof(*vg), GFP_KERNEL);
if (!vg)
return -ENOMEM;
vg->pdev = pdev;
vg->dev = dev;
ret = byt_set_soc_data(vg, soc_data);
if (ret) {
dev_err(&pdev->dev, "failed to set soc data\n");
dev_err(dev, "failed to set soc data\n");
return ret;
}
vg->pctl_desc = byt_pinctrl_desc;
vg->pctl_desc.name = dev_name(&pdev->dev);
vg->pctl_desc.pins = vg->soc_data->pins;
vg->pctl_desc.npins = vg->soc_data->npins;
vg->pctldesc = byt_pinctrl_desc;
vg->pctldesc.name = dev_name(dev);
vg->pctldesc.pins = vg->soc->pins;
vg->pctldesc.npins = vg->soc->npins;
vg->pctl_dev = devm_pinctrl_register(&pdev->dev, &vg->pctl_desc, vg);
if (IS_ERR(vg->pctl_dev)) {
dev_err(&pdev->dev, "failed to register pinctrl driver\n");
return PTR_ERR(vg->pctl_dev);
vg->pctldev = devm_pinctrl_register(dev, &vg->pctldesc, vg);
if (IS_ERR(vg->pctldev)) {
dev_err(dev, "failed to register pinctrl driver\n");
return PTR_ERR(vg->pctldev);
}
ret = byt_gpio_probe(vg);
@ -1657,7 +1646,7 @@ static int byt_pinctrl_probe(struct platform_device *pdev)
return ret;
platform_set_drvdata(pdev, vg);
pm_runtime_enable(&pdev->dev);
pm_runtime_enable(dev);
return 0;
}
@ -1665,30 +1654,30 @@ static int byt_pinctrl_probe(struct platform_device *pdev)
#ifdef CONFIG_PM_SLEEP
static int byt_gpio_suspend(struct device *dev)
{
struct byt_gpio *vg = dev_get_drvdata(dev);
struct intel_pinctrl *vg = dev_get_drvdata(dev);
unsigned long flags;
int i;
raw_spin_lock_irqsave(&byt_lock, flags);
for (i = 0; i < vg->soc_data->npins; i++) {
for (i = 0; i < vg->soc->npins; i++) {
void __iomem *reg;
u32 value;
unsigned int pin = vg->soc_data->pins[i].number;
unsigned int pin = vg->soc->pins[i].number;
reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
if (!reg) {
dev_warn(&vg->pdev->dev,
dev_warn(vg->dev,
"Pin %i: could not retrieve conf0 register\n",
i);
continue;
}
value = readl(reg) & BYT_CONF0_RESTORE_MASK;
vg->saved_context[i].conf0 = value;
vg->context.pads[i].conf0 = value;
reg = byt_gpio_reg(vg, pin, BYT_VAL_REG);
value = readl(reg) & BYT_VAL_RESTORE_MASK;
vg->saved_context[i].val = value;
vg->context.pads[i].val = value;
}
raw_spin_unlock_irqrestore(&byt_lock, flags);
@ -1697,29 +1686,29 @@ static int byt_gpio_suspend(struct device *dev)
static int byt_gpio_resume(struct device *dev)
{
struct byt_gpio *vg = dev_get_drvdata(dev);
struct intel_pinctrl *vg = dev_get_drvdata(dev);
unsigned long flags;
int i;
raw_spin_lock_irqsave(&byt_lock, flags);
for (i = 0; i < vg->soc_data->npins; i++) {
for (i = 0; i < vg->soc->npins; i++) {
void __iomem *reg;
u32 value;
unsigned int pin = vg->soc_data->pins[i].number;
unsigned int pin = vg->soc->pins[i].number;
reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
if (!reg) {
dev_warn(&vg->pdev->dev,
dev_warn(vg->dev,
"Pin %i: could not retrieve conf0 register\n",
i);
continue;
}
value = readl(reg);
if ((value & BYT_CONF0_RESTORE_MASK) !=
vg->saved_context[i].conf0) {
vg->context.pads[i].conf0) {
value &= ~BYT_CONF0_RESTORE_MASK;
value |= vg->saved_context[i].conf0;
value |= vg->context.pads[i].conf0;
writel(value, reg);
dev_info(dev, "restored pin %d conf0 %#08x", i, value);
}
@ -1727,11 +1716,11 @@ static int byt_gpio_resume(struct device *dev)
reg = byt_gpio_reg(vg, pin, BYT_VAL_REG);
value = readl(reg);
if ((value & BYT_VAL_RESTORE_MASK) !=
vg->saved_context[i].val) {
vg->context.pads[i].val) {
u32 v;
v = value & ~BYT_VAL_RESTORE_MASK;
v |= vg->saved_context[i].val;
v |= vg->context.pads[i].val;
if (v != value) {
writel(v, reg);
dev_dbg(dev, "restored pin %d val %#08x\n",

View file

@ -1289,7 +1289,10 @@ static int chv_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
direction = ctrl0 & CHV_PADCTRL0_GPIOCFG_MASK;
direction >>= CHV_PADCTRL0_GPIOCFG_SHIFT;
return direction != CHV_PADCTRL0_GPIOCFG_GPO;
if (direction == CHV_PADCTRL0_GPIOCFG_GPO)
return GPIO_LINE_DIRECTION_OUT;
return GPIO_LINE_DIRECTION_IN;
}
static int chv_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)

View file

@ -8,8 +8,8 @@
*/
#include <linux/acpi.h>
#include <linux/interrupt.h>
#include <linux/gpio/driver.h>
#include <linux/interrupt.h>
#include <linux/log2.h>
#include <linux/module.h>
#include <linux/platform_device.h>
@ -85,39 +85,6 @@ struct intel_community_context {
u32 *hostown;
};
struct intel_pinctrl_context {
struct intel_pad_context *pads;
struct intel_community_context *communities;
};
/**
* struct intel_pinctrl - Intel pinctrl private structure
* @dev: Pointer to the device structure
* @lock: Lock to serialize register access
* @pctldesc: Pin controller description
* @pctldev: Pointer to the pin controller device
* @chip: GPIO chip in this pin controller
* @irqchip: IRQ chip in this pin controller
* @soc: SoC/PCH specific pin configuration data
* @communities: All communities in this pin controller
* @ncommunities: Number of communities in this pin controller
* @context: Configuration saved over system sleep
* @irq: pinctrl/GPIO chip irq number
*/
struct intel_pinctrl {
struct device *dev;
raw_spinlock_t lock;
struct pinctrl_desc pctldesc;
struct pinctrl_dev *pctldev;
struct gpio_chip chip;
struct irq_chip irqchip;
const struct intel_pinctrl_soc_data *soc;
struct intel_community *communities;
size_t ncommunities;
struct intel_pinctrl_context context;
int irq;
};
#define pin_to_padno(c, p) ((p) - (c)->pin_base)
#define padgroup_offset(g, p) ((p) - (g)->base)
@ -944,7 +911,10 @@ static int intel_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
if (padcfg0 & PADCFG0_PMODE_MASK)
return -EINVAL;
return !!(padcfg0 & PADCFG0_GPIOTXDIS);
if (padcfg0 & PADCFG0_GPIOTXDIS)
return GPIO_LINE_DIRECTION_IN;
return GPIO_LINE_DIRECTION_OUT;
}
static int intel_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
@ -1160,8 +1130,8 @@ static irqreturn_t intel_gpio_irq(int irq, void *data)
return ret;
}
static int intel_gpio_add_pin_ranges(struct intel_pinctrl *pctrl,
const struct intel_community *community)
static int intel_gpio_add_community_ranges(struct intel_pinctrl *pctrl,
const struct intel_community *community)
{
int ret = 0, i;
@ -1181,6 +1151,24 @@ static int intel_gpio_add_pin_ranges(struct intel_pinctrl *pctrl,
return ret;
}
static int intel_gpio_add_pin_ranges(struct gpio_chip *gc)
{
struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
int ret, i;
for (i = 0; i < pctrl->ncommunities; i++) {
struct intel_community *community = &pctrl->communities[i];
ret = intel_gpio_add_community_ranges(pctrl, community);
if (ret) {
dev_err(pctrl->dev, "failed to add GPIO pin range\n");
return ret;
}
}
return 0;
}
static unsigned int intel_gpio_ngpio(const struct intel_pinctrl *pctrl)
{
const struct intel_community *community;
@ -1205,7 +1193,8 @@ static unsigned int intel_gpio_ngpio(const struct intel_pinctrl *pctrl)
static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq)
{
int ret, i;
int ret;
struct gpio_irq_chip *girq;
pctrl->chip = intel_gpio_chip;
@ -1214,6 +1203,7 @@ static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq)
pctrl->chip.label = dev_name(pctrl->dev);
pctrl->chip.parent = pctrl->dev;
pctrl->chip.base = -1;
pctrl->chip.add_pin_ranges = intel_gpio_add_pin_ranges;
pctrl->irq = irq;
/* Setup IRQ chip */
@ -1225,26 +1215,9 @@ static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq)
pctrl->irqchip.irq_set_wake = intel_gpio_irq_wake;
pctrl->irqchip.flags = IRQCHIP_MASK_ON_SUSPEND;
ret = devm_gpiochip_add_data(pctrl->dev, &pctrl->chip, pctrl);
if (ret) {
dev_err(pctrl->dev, "failed to register gpiochip\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;
}
}
/*
* We need to request the interrupt here (instead of providing chip
* to the irq directly) because on some platforms several GPIO
* controllers share the same interrupt line.
* On some platforms several GPIO controllers share the same interrupt
* line.
*/
ret = devm_request_irq(pctrl->dev, irq, intel_gpio_irq,
IRQF_SHARED | IRQF_NO_THREAD,
@ -1254,14 +1227,20 @@ static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq)
return ret;
}
ret = gpiochip_irqchip_add(&pctrl->chip, &pctrl->irqchip, 0,
handle_bad_irq, IRQ_TYPE_NONE);
girq = &pctrl->chip.irq;
girq->chip = &pctrl->irqchip;
/* This will let us handle the IRQ in the driver */
girq->parent_handler = NULL;
girq->num_parents = 0;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_bad_irq;
ret = devm_gpiochip_add_data(pctrl->dev, &pctrl->chip, pctrl);
if (ret) {
dev_err(pctrl->dev, "failed to add irqchip\n");
dev_err(pctrl->dev, "failed to register gpiochip\n");
return ret;
}
gpiochip_set_chained_irqchip(&pctrl->chip, &pctrl->irqchip, irq, NULL);
return 0;
}

View file

@ -10,7 +10,10 @@
#ifndef PINCTRL_INTEL_H
#define PINCTRL_INTEL_H
#include <linux/gpio/driver.h>
#include <linux/irq.h>
#include <linux/pm.h>
#include <linux/spinlock_types.h>
struct pinctrl_pin_desc;
struct platform_device;
@ -174,6 +177,47 @@ struct intel_pinctrl_soc_data {
size_t ncommunities;
};
struct intel_pad_context;
struct intel_community_context;
/**
* struct intel_pinctrl_context - context to be saved during suspend-resume
* @pads: Opaque context per pad (driver dependent)
* @communities: Opaque context per community (driver dependent)
*/
struct intel_pinctrl_context {
struct intel_pad_context *pads;
struct intel_community_context *communities;
};
/**
* struct intel_pinctrl - Intel pinctrl private structure
* @dev: Pointer to the device structure
* @lock: Lock to serialize register access
* @pctldesc: Pin controller description
* @pctldev: Pointer to the pin controller device
* @chip: GPIO chip in this pin controller
* @irqchip: IRQ chip in this pin controller
* @soc: SoC/PCH specific pin configuration data
* @communities: All communities in this pin controller
* @ncommunities: Number of communities in this pin controller
* @context: Configuration saved over system sleep
* @irq: pinctrl/GPIO chip irq number
*/
struct intel_pinctrl {
struct device *dev;
raw_spinlock_t lock;
struct pinctrl_desc pctldesc;
struct pinctrl_dev *pctldev;
struct gpio_chip chip;
struct irq_chip irqchip;
const struct intel_pinctrl_soc_data *soc;
struct intel_community *communities;
size_t ncommunities;
struct intel_pinctrl_context context;
int irq;
};
int intel_pinctrl_probe_by_hid(struct platform_device *pdev);
int intel_pinctrl_probe_by_uid(struct platform_device *pdev);

View file

@ -0,0 +1,975 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Intel Lynxpoint PCH pinctrl/GPIO driver
*
* Copyright (c) 2012, 2019, Intel Corporation
* Authors: Mathias Nyman <mathias.nyman@linux.intel.com>
* Andy Shevchenko <andriy.shevchenko@linux.intel.com>
*/
#include <linux/acpi.h>
#include <linux/bitops.h>
#include <linux/gpio/driver.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinconf-generic.h>
#include "pinctrl-intel.h"
#define COMMUNITY(p, n) \
{ \
.pin_base = (p), \
.npins = (n), \
}
static const struct pinctrl_pin_desc lptlp_pins[] = {
PINCTRL_PIN(0, "GP0_UART1_RXD"),
PINCTRL_PIN(1, "GP1_UART1_TXD"),
PINCTRL_PIN(2, "GP2_UART1_RTSB"),
PINCTRL_PIN(3, "GP3_UART1_CTSB"),
PINCTRL_PIN(4, "GP4_I2C0_SDA"),
PINCTRL_PIN(5, "GP5_I2C0_SCL"),
PINCTRL_PIN(6, "GP6_I2C1_SDA"),
PINCTRL_PIN(7, "GP7_I2C1_SCL"),
PINCTRL_PIN(8, "GP8"),
PINCTRL_PIN(9, "GP9"),
PINCTRL_PIN(10, "GP10"),
PINCTRL_PIN(11, "GP11_SMBALERTB"),
PINCTRL_PIN(12, "GP12_LANPHYPC"),
PINCTRL_PIN(13, "GP13"),
PINCTRL_PIN(14, "GP14"),
PINCTRL_PIN(15, "GP15"),
PINCTRL_PIN(16, "GP16_MGPIO9"),
PINCTRL_PIN(17, "GP17_MGPIO10"),
PINCTRL_PIN(18, "GP18_SRC0CLKRQB"),
PINCTRL_PIN(19, "GP19_SRC1CLKRQB"),
PINCTRL_PIN(20, "GP20_SRC2CLKRQB"),
PINCTRL_PIN(21, "GP21_SRC3CLKRQB"),
PINCTRL_PIN(22, "GP22_SRC4CLKRQB_TRST2"),
PINCTRL_PIN(23, "GP23_SRC5CLKRQB_TDI2"),
PINCTRL_PIN(24, "GP24_MGPIO0"),
PINCTRL_PIN(25, "GP25_USBWAKEOUTB"),
PINCTRL_PIN(26, "GP26_MGPIO5"),
PINCTRL_PIN(27, "GP27_MGPIO6"),
PINCTRL_PIN(28, "GP28_MGPIO7"),
PINCTRL_PIN(29, "GP29_SLP_WLANB_MGPIO3"),
PINCTRL_PIN(30, "GP30_SUSWARNB_SUSPWRDNACK_MGPIO1"),
PINCTRL_PIN(31, "GP31_ACPRESENT_MGPIO2"),
PINCTRL_PIN(32, "GP32_CLKRUNB"),
PINCTRL_PIN(33, "GP33_DEVSLP0"),
PINCTRL_PIN(34, "GP34_SATA0XPCIE6L3B_SATA0GP"),
PINCTRL_PIN(35, "GP35_SATA1XPCIE6L2B_SATA1GP"),
PINCTRL_PIN(36, "GP36_SATA2XPCIE6L1B_SATA2GP"),
PINCTRL_PIN(37, "GP37_SATA3XPCIE6L0B_SATA3GP"),
PINCTRL_PIN(38, "GP38_DEVSLP1"),
PINCTRL_PIN(39, "GP39_DEVSLP2"),
PINCTRL_PIN(40, "GP40_OC0B"),
PINCTRL_PIN(41, "GP41_OC1B"),
PINCTRL_PIN(42, "GP42_OC2B"),
PINCTRL_PIN(43, "GP43_OC3B"),
PINCTRL_PIN(44, "GP44"),
PINCTRL_PIN(45, "GP45_TMS2"),
PINCTRL_PIN(46, "GP46_TDO2"),
PINCTRL_PIN(47, "GP47"),
PINCTRL_PIN(48, "GP48"),
PINCTRL_PIN(49, "GP49"),
PINCTRL_PIN(50, "GP50"),
PINCTRL_PIN(51, "GP51_GSXDOUT"),
PINCTRL_PIN(52, "GP52_GSXSLOAD"),
PINCTRL_PIN(53, "GP53_GSXDIN"),
PINCTRL_PIN(54, "GP54_GSXSRESETB"),
PINCTRL_PIN(55, "GP55_GSXCLK"),
PINCTRL_PIN(56, "GP56"),
PINCTRL_PIN(57, "GP57"),
PINCTRL_PIN(58, "GP58"),
PINCTRL_PIN(59, "GP59"),
PINCTRL_PIN(60, "GP60_SML0ALERTB_MGPIO4"),
PINCTRL_PIN(61, "GP61_SUS_STATB"),
PINCTRL_PIN(62, "GP62_SUSCLK"),
PINCTRL_PIN(63, "GP63_SLP_S5B"),
PINCTRL_PIN(64, "GP64_SDIO_CLK"),
PINCTRL_PIN(65, "GP65_SDIO_CMD"),
PINCTRL_PIN(66, "GP66_SDIO_D0"),
PINCTRL_PIN(67, "GP67_SDIO_D1"),
PINCTRL_PIN(68, "GP68_SDIO_D2"),
PINCTRL_PIN(69, "GP69_SDIO_D3"),
PINCTRL_PIN(70, "GP70_SDIO_POWER_EN"),
PINCTRL_PIN(71, "GP71_MPHYPC"),
PINCTRL_PIN(72, "GP72_BATLOWB"),
PINCTRL_PIN(73, "GP73_SML1ALERTB_PCHHOTB_MGPIO8"),
PINCTRL_PIN(74, "GP74_SML1DATA_MGPIO12"),
PINCTRL_PIN(75, "GP75_SML1CLK_MGPIO11"),
PINCTRL_PIN(76, "GP76_BMBUSYB"),
PINCTRL_PIN(77, "GP77_PIRQAB"),
PINCTRL_PIN(78, "GP78_PIRQBB"),
PINCTRL_PIN(79, "GP79_PIRQCB"),
PINCTRL_PIN(80, "GP80_PIRQDB"),
PINCTRL_PIN(81, "GP81_SPKR"),
PINCTRL_PIN(82, "GP82_RCINB"),
PINCTRL_PIN(83, "GP83_GSPI0_CSB"),
PINCTRL_PIN(84, "GP84_GSPI0_CLK"),
PINCTRL_PIN(85, "GP85_GSPI0_MISO"),
PINCTRL_PIN(86, "GP86_GSPI0_MOSI"),
PINCTRL_PIN(87, "GP87_GSPI1_CSB"),
PINCTRL_PIN(88, "GP88_GSPI1_CLK"),
PINCTRL_PIN(89, "GP89_GSPI1_MISO"),
PINCTRL_PIN(90, "GP90_GSPI1_MOSI"),
PINCTRL_PIN(91, "GP91_UART0_RXD"),
PINCTRL_PIN(92, "GP92_UART0_TXD"),
PINCTRL_PIN(93, "GP93_UART0_RTSB"),
PINCTRL_PIN(94, "GP94_UART0_CTSB"),
};
static const struct intel_community lptlp_communities[] = {
COMMUNITY(0, 95),
};
static const struct intel_pinctrl_soc_data lptlp_soc_data = {
.pins = lptlp_pins,
.npins = ARRAY_SIZE(lptlp_pins),
.communities = lptlp_communities,
.ncommunities = ARRAY_SIZE(lptlp_communities),
};
/* LynxPoint chipset has support for 95 GPIO pins */
#define LP_NUM_GPIO 95
/* Bitmapped register offsets */
#define LP_ACPI_OWNED 0x00 /* Bitmap, set by bios, 0: pin reserved for ACPI */
#define LP_IRQ2IOXAPIC 0x10 /* Bitmap, set by bios, 1: pin routed to IOxAPIC */
#define LP_GC 0x7C /* set APIC IRQ to IRQ14 or IRQ15 for all pins */
#define LP_INT_STAT 0x80
#define LP_INT_ENABLE 0x90
/* Each pin has two 32 bit config registers, starting at 0x100 */
#define LP_CONFIG1 0x100
#define LP_CONFIG2 0x104
/* LP_CONFIG1 reg bits */
#define OUT_LVL_BIT BIT(31)
#define IN_LVL_BIT BIT(30)
#define TRIG_SEL_BIT BIT(4) /* 0: Edge, 1: Level */
#define INT_INV_BIT BIT(3) /* Invert interrupt triggering */
#define DIR_BIT BIT(2) /* 0: Output, 1: Input */
#define USE_SEL_MASK GENMASK(1, 0) /* 0: Native, 1: GPIO, ... */
#define USE_SEL_NATIVE (0 << 0)
#define USE_SEL_GPIO (1 << 0)
/* LP_CONFIG2 reg bits */
#define GPINDIS_BIT BIT(2) /* disable input sensing */
#define GPIWP_MASK GENMASK(1, 0) /* weak pull options */
#define GPIWP_NONE 0 /* none */
#define GPIWP_DOWN 1 /* weak pull down */
#define GPIWP_UP 2 /* weak pull up */
/*
* Lynxpoint gpios are controlled through both bitmapped registers and
* per gpio specific registers. The bitmapped registers are in chunks of
* 3 x 32bit registers to cover all 95 GPIOs
*
* per gpio specific registers consist of two 32bit registers per gpio
* (LP_CONFIG1 and LP_CONFIG2), with 95 GPIOs there's a total of
* 190 config registers.
*
* A simplified view of the register layout look like this:
*
* LP_ACPI_OWNED[31:0] gpio ownerships for gpios 0-31 (bitmapped registers)
* LP_ACPI_OWNED[63:32] gpio ownerships for gpios 32-63
* LP_ACPI_OWNED[94:64] gpio ownerships for gpios 63-94
* ...
* LP_INT_ENABLE[31:0] ...
* LP_INT_ENABLE[63:32] ...
* LP_INT_ENABLE[94:64] ...
* LP0_CONFIG1 (gpio 0) config1 reg for gpio 0 (per gpio registers)
* LP0_CONFIG2 (gpio 0) config2 reg for gpio 0
* LP1_CONFIG1 (gpio 1) config1 reg for gpio 1
* LP1_CONFIG2 (gpio 1) config2 reg for gpio 1
* LP2_CONFIG1 (gpio 2) ...
* LP2_CONFIG2 (gpio 2) ...
* ...
* LP94_CONFIG1 (gpio 94) ...
* LP94_CONFIG2 (gpio 94) ...
*
* IOxAPIC redirection map applies only for gpio 8-10, 13-14, 45-55.
*/
static struct intel_community *lp_get_community(struct intel_pinctrl *lg,
unsigned int pin)
{
struct intel_community *comm;
int i;
for (i = 0; i < lg->ncommunities; i++) {
comm = &lg->communities[i];
if (pin < comm->pin_base + comm->npins && pin >= comm->pin_base)
return comm;
}
return NULL;
}
static void __iomem *lp_gpio_reg(struct gpio_chip *chip, unsigned int offset,
int reg)
{
struct intel_pinctrl *lg = gpiochip_get_data(chip);
struct intel_community *comm;
int reg_offset;
comm = lp_get_community(lg, offset);
if (!comm)
return NULL;
offset -= comm->pin_base;
if (reg == LP_CONFIG1 || reg == LP_CONFIG2)
/* per gpio specific config registers */
reg_offset = offset * 8;
else
/* bitmapped registers */
reg_offset = (offset / 32) * 4;
return comm->regs + reg_offset + reg;
}
static bool lp_gpio_acpi_use(struct intel_pinctrl *lg, unsigned int pin)
{
void __iomem *acpi_use;
acpi_use = lp_gpio_reg(&lg->chip, pin, LP_ACPI_OWNED);
if (!acpi_use)
return true;
return !(ioread32(acpi_use) & BIT(pin % 32));
}
static bool lp_gpio_ioxapic_use(struct gpio_chip *chip, unsigned int offset)
{
void __iomem *ioxapic_use = lp_gpio_reg(chip, offset, LP_IRQ2IOXAPIC);
u32 value;
value = ioread32(ioxapic_use);
if (offset >= 8 && offset <= 10)
return !!(value & BIT(offset - 8 + 0));
if (offset >= 13 && offset <= 14)
return !!(value & BIT(offset - 13 + 3));
if (offset >= 45 && offset <= 55)
return !!(value & BIT(offset - 45 + 5));
return false;
}
static int lp_get_groups_count(struct pinctrl_dev *pctldev)
{
struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev);
return lg->soc->ngroups;
}
static const char *lp_get_group_name(struct pinctrl_dev *pctldev,
unsigned int selector)
{
struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev);
return lg->soc->groups[selector].name;
}
static int lp_get_group_pins(struct pinctrl_dev *pctldev,
unsigned int selector,
const unsigned int **pins,
unsigned int *num_pins)
{
struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev);
*pins = lg->soc->groups[selector].pins;
*num_pins = lg->soc->groups[selector].npins;
return 0;
}
static void lp_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
unsigned int pin)
{
struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev);
void __iomem *reg = lp_gpio_reg(&lg->chip, pin, LP_CONFIG1);
void __iomem *conf2 = lp_gpio_reg(&lg->chip, pin, LP_CONFIG2);
u32 value, mode;
value = ioread32(reg);
mode = value & USE_SEL_MASK;
if (mode == USE_SEL_GPIO)
seq_puts(s, "GPIO ");
else
seq_printf(s, "mode %d ", mode);
seq_printf(s, "0x%08x 0x%08x", value, ioread32(conf2));
if (lp_gpio_acpi_use(lg, pin))
seq_puts(s, " [ACPI]");
}
static const struct pinctrl_ops lptlp_pinctrl_ops = {
.get_groups_count = lp_get_groups_count,
.get_group_name = lp_get_group_name,
.get_group_pins = lp_get_group_pins,
.pin_dbg_show = lp_pin_dbg_show,
};
static int lp_get_functions_count(struct pinctrl_dev *pctldev)
{
struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev);
return lg->soc->nfunctions;
}
static const char *lp_get_function_name(struct pinctrl_dev *pctldev,
unsigned int selector)
{
struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev);
return lg->soc->functions[selector].name;
}
static int lp_get_function_groups(struct pinctrl_dev *pctldev,
unsigned int selector,
const char * const **groups,
unsigned int *num_groups)
{
struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev);
*groups = lg->soc->functions[selector].groups;
*num_groups = lg->soc->functions[selector].ngroups;
return 0;
}
static int lp_pinmux_set_mux(struct pinctrl_dev *pctldev,
unsigned int function, unsigned int group)
{
struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev);
const struct intel_pingroup *grp = &lg->soc->groups[group];
unsigned long flags;
int i;
raw_spin_lock_irqsave(&lg->lock, flags);
/* Now enable the mux setting for each pin in the group */
for (i = 0; i < grp->npins; i++) {
void __iomem *reg = lp_gpio_reg(&lg->chip, grp->pins[i], LP_CONFIG1);
u32 value;
value = ioread32(reg);
value &= ~USE_SEL_MASK;
if (grp->modes)
value |= grp->modes[i];
else
value |= grp->mode;
iowrite32(value, reg);
}
raw_spin_unlock_irqrestore(&lg->lock, flags);
return 0;
}
static int lp_gpio_request_enable(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned int pin)
{
struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev);
void __iomem *reg = lp_gpio_reg(&lg->chip, pin, LP_CONFIG1);
void __iomem *conf2 = lp_gpio_reg(&lg->chip, pin, LP_CONFIG2);
unsigned long flags;
u32 value;
pm_runtime_get(lg->dev);
raw_spin_lock_irqsave(&lg->lock, flags);
/*
* Reconfigure pin to GPIO mode if needed and issue a warning,
* since we expect firmware to configure it properly.
*/
value = ioread32(reg);
if ((value & USE_SEL_MASK) != USE_SEL_GPIO) {
iowrite32((value & USE_SEL_MASK) | USE_SEL_GPIO, reg);
dev_warn(lg->dev, FW_BUG "pin %u forcibly reconfigured as GPIO\n", pin);
}
/* Enable input sensing */
iowrite32(ioread32(conf2) & ~GPINDIS_BIT, conf2);
raw_spin_unlock_irqrestore(&lg->lock, flags);
return 0;
}
static void lp_gpio_disable_free(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned int pin)
{
struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev);
void __iomem *conf2 = lp_gpio_reg(&lg->chip, pin, LP_CONFIG2);
unsigned long flags;
raw_spin_lock_irqsave(&lg->lock, flags);
/* Disable input sensing */
iowrite32(ioread32(conf2) | GPINDIS_BIT, conf2);
raw_spin_unlock_irqrestore(&lg->lock, flags);
pm_runtime_put(lg->dev);
}
static int lp_gpio_set_direction(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned int pin, bool input)
{
struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev);
void __iomem *reg = lp_gpio_reg(&lg->chip, pin, LP_CONFIG1);
unsigned long flags;
u32 value;
raw_spin_lock_irqsave(&lg->lock, flags);
value = ioread32(reg);
value &= ~DIR_BIT;
if (input) {
value |= DIR_BIT;
} else {
/*
* Before making any direction modifications, do a check if GPIO
* is set for direct IRQ. On Lynxpoint, setting GPIO to output
* does not make sense, so let's at least warn the caller before
* they shoot themselves in the foot.
*/
WARN(lp_gpio_ioxapic_use(&lg->chip, pin),
"Potential Error: Setting GPIO to output with IOxAPIC redirection");
}
iowrite32(value, reg);
raw_spin_unlock_irqrestore(&lg->lock, flags);
return 0;
}
static const struct pinmux_ops lptlp_pinmux_ops = {
.get_functions_count = lp_get_functions_count,
.get_function_name = lp_get_function_name,
.get_function_groups = lp_get_function_groups,
.set_mux = lp_pinmux_set_mux,
.gpio_request_enable = lp_gpio_request_enable,
.gpio_disable_free = lp_gpio_disable_free,
.gpio_set_direction = lp_gpio_set_direction,
};
static int lp_pin_config_get(struct pinctrl_dev *pctldev, unsigned int pin,
unsigned long *config)
{
struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev);
void __iomem *conf2 = lp_gpio_reg(&lg->chip, pin, LP_CONFIG2);
enum pin_config_param param = pinconf_to_config_param(*config);
unsigned long flags;
u32 value, pull;
u16 arg = 0;
raw_spin_lock_irqsave(&lg->lock, flags);
value = ioread32(conf2);
raw_spin_unlock_irqrestore(&lg->lock, flags);
pull = value & GPIWP_MASK;
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
if (pull)
return -EINVAL;
break;
case PIN_CONFIG_BIAS_PULL_DOWN:
if (pull != GPIWP_DOWN)
return -EINVAL;
arg = 1;
break;
case PIN_CONFIG_BIAS_PULL_UP:
if (pull != GPIWP_UP)
return -EINVAL;
arg = 1;
break;
default:
return -ENOTSUPP;
}
*config = pinconf_to_config_packed(param, arg);
return 0;
}
static int lp_pin_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
unsigned long *configs, unsigned int num_configs)
{
struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev);
void __iomem *conf2 = lp_gpio_reg(&lg->chip, pin, LP_CONFIG2);
enum pin_config_param param;
unsigned long flags;
int i, ret = 0;
u32 value;
raw_spin_lock_irqsave(&lg->lock, flags);
value = ioread32(conf2);
for (i = 0; i < num_configs; i++) {
param = pinconf_to_config_param(configs[i]);
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
value &= ~GPIWP_MASK;
break;
case PIN_CONFIG_BIAS_PULL_DOWN:
value &= ~GPIWP_MASK;
value |= GPIWP_DOWN;
break;
case PIN_CONFIG_BIAS_PULL_UP:
value &= ~GPIWP_MASK;
value |= GPIWP_UP;
break;
default:
ret = -ENOTSUPP;
}
if (ret)
break;
}
if (!ret)
iowrite32(value, conf2);
raw_spin_unlock_irqrestore(&lg->lock, flags);
return ret;
}
static const struct pinconf_ops lptlp_pinconf_ops = {
.is_generic = true,
.pin_config_get = lp_pin_config_get,
.pin_config_set = lp_pin_config_set,
};
static const struct pinctrl_desc lptlp_pinctrl_desc = {
.pctlops = &lptlp_pinctrl_ops,
.pmxops = &lptlp_pinmux_ops,
.confops = &lptlp_pinconf_ops,
.owner = THIS_MODULE,
};
static int lp_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
void __iomem *reg = lp_gpio_reg(chip, offset, LP_CONFIG1);
return !!(ioread32(reg) & IN_LVL_BIT);
}
static void lp_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
{
struct intel_pinctrl *lg = gpiochip_get_data(chip);
void __iomem *reg = lp_gpio_reg(chip, offset, LP_CONFIG1);
unsigned long flags;
raw_spin_lock_irqsave(&lg->lock, flags);
if (value)
iowrite32(ioread32(reg) | OUT_LVL_BIT, reg);
else
iowrite32(ioread32(reg) & ~OUT_LVL_BIT, reg);
raw_spin_unlock_irqrestore(&lg->lock, flags);
}
static int lp_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
{
return pinctrl_gpio_direction_input(chip->base + offset);
}
static int lp_gpio_direction_output(struct gpio_chip *chip, unsigned int offset,
int value)
{
lp_gpio_set(chip, offset, value);
return pinctrl_gpio_direction_output(chip->base + offset);
}
static int lp_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
{
void __iomem *reg = lp_gpio_reg(chip, offset, LP_CONFIG1);
if (ioread32(reg) & DIR_BIT)
return GPIO_LINE_DIRECTION_IN;
return GPIO_LINE_DIRECTION_OUT;
}
static void lp_gpio_irq_handler(struct irq_desc *desc)
{
struct irq_data *data = irq_desc_get_irq_data(desc);
struct gpio_chip *gc = irq_desc_get_handler_data(desc);
struct intel_pinctrl *lg = gpiochip_get_data(gc);
struct irq_chip *chip = irq_data_get_irq_chip(data);
void __iomem *reg, *ena;
unsigned long pending;
u32 base, pin;
/* check from GPIO controller which pin triggered the interrupt */
for (base = 0; base < lg->chip.ngpio; base += 32) {
reg = lp_gpio_reg(&lg->chip, base, LP_INT_STAT);
ena = lp_gpio_reg(&lg->chip, base, LP_INT_ENABLE);
/* Only interrupts that are enabled */
pending = ioread32(reg) & ioread32(ena);
for_each_set_bit(pin, &pending, 32) {
unsigned int irq;
irq = irq_find_mapping(lg->chip.irq.domain, base + pin);
generic_handle_irq(irq);
}
}
chip->irq_eoi(data);
}
static void lp_irq_ack(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct intel_pinctrl *lg = gpiochip_get_data(gc);
u32 hwirq = irqd_to_hwirq(d);
void __iomem *reg = lp_gpio_reg(&lg->chip, hwirq, LP_INT_STAT);
unsigned long flags;
raw_spin_lock_irqsave(&lg->lock, flags);
iowrite32(BIT(hwirq % 32), reg);
raw_spin_unlock_irqrestore(&lg->lock, flags);
}
static void lp_irq_unmask(struct irq_data *d)
{
}
static void lp_irq_mask(struct irq_data *d)
{
}
static void lp_irq_enable(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct intel_pinctrl *lg = gpiochip_get_data(gc);
u32 hwirq = irqd_to_hwirq(d);
void __iomem *reg = lp_gpio_reg(&lg->chip, hwirq, LP_INT_ENABLE);
unsigned long flags;
raw_spin_lock_irqsave(&lg->lock, flags);
iowrite32(ioread32(reg) | BIT(hwirq % 32), reg);
raw_spin_unlock_irqrestore(&lg->lock, flags);
}
static void lp_irq_disable(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct intel_pinctrl *lg = gpiochip_get_data(gc);
u32 hwirq = irqd_to_hwirq(d);
void __iomem *reg = lp_gpio_reg(&lg->chip, hwirq, LP_INT_ENABLE);
unsigned long flags;
raw_spin_lock_irqsave(&lg->lock, flags);
iowrite32(ioread32(reg) & ~BIT(hwirq % 32), reg);
raw_spin_unlock_irqrestore(&lg->lock, flags);
}
static int lp_irq_set_type(struct irq_data *d, unsigned int type)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct intel_pinctrl *lg = gpiochip_get_data(gc);
u32 hwirq = irqd_to_hwirq(d);
void __iomem *reg = lp_gpio_reg(&lg->chip, hwirq, LP_CONFIG1);
unsigned long flags;
u32 value;
if (hwirq >= lg->chip.ngpio)
return -EINVAL;
/* Fail if BIOS reserved pin for ACPI use */
if (lp_gpio_acpi_use(lg, hwirq)) {
dev_err(lg->dev, "pin %u can't be used as IRQ\n", hwirq);
return -EBUSY;
}
raw_spin_lock_irqsave(&lg->lock, flags);
value = ioread32(reg);
/* set both TRIG_SEL and INV bits to 0 for rising edge */
if (type & IRQ_TYPE_EDGE_RISING)
value &= ~(TRIG_SEL_BIT | INT_INV_BIT);
/* TRIG_SEL bit 0, INV bit 1 for falling edge */
if (type & IRQ_TYPE_EDGE_FALLING)
value = (value | INT_INV_BIT) & ~TRIG_SEL_BIT;
/* TRIG_SEL bit 1, INV bit 0 for level low */
if (type & IRQ_TYPE_LEVEL_LOW)
value = (value | TRIG_SEL_BIT) & ~INT_INV_BIT;
/* TRIG_SEL bit 1, INV bit 1 for level high */
if (type & IRQ_TYPE_LEVEL_HIGH)
value |= TRIG_SEL_BIT | INT_INV_BIT;
iowrite32(value, reg);
if (type & IRQ_TYPE_EDGE_BOTH)
irq_set_handler_locked(d, handle_edge_irq);
else if (type & IRQ_TYPE_LEVEL_MASK)
irq_set_handler_locked(d, handle_level_irq);
raw_spin_unlock_irqrestore(&lg->lock, flags);
return 0;
}
static struct irq_chip lp_irqchip = {
.name = "LP-GPIO",
.irq_ack = lp_irq_ack,
.irq_mask = lp_irq_mask,
.irq_unmask = lp_irq_unmask,
.irq_enable = lp_irq_enable,
.irq_disable = lp_irq_disable,
.irq_set_type = lp_irq_set_type,
.flags = IRQCHIP_SKIP_SET_WAKE,
};
static int lp_gpio_irq_init_hw(struct gpio_chip *chip)
{
struct intel_pinctrl *lg = gpiochip_get_data(chip);
void __iomem *reg;
unsigned int base;
for (base = 0; base < lg->chip.ngpio; base += 32) {
/* disable gpio pin interrupts */
reg = lp_gpio_reg(&lg->chip, base, LP_INT_ENABLE);
iowrite32(0, reg);
/* Clear interrupt status register */
reg = lp_gpio_reg(&lg->chip, base, LP_INT_STAT);
iowrite32(0xffffffff, reg);
}
return 0;
}
static int lp_gpio_add_pin_ranges(struct gpio_chip *chip)
{
struct intel_pinctrl *lg = gpiochip_get_data(chip);
struct device *dev = lg->dev;
int ret;
ret = gpiochip_add_pin_range(chip, dev_name(dev), 0, 0, lg->soc->npins);
if (ret)
dev_err(dev, "failed to add GPIO pin range\n");
return ret;
}
static int lp_gpio_probe(struct platform_device *pdev)
{
const struct intel_pinctrl_soc_data *soc;
struct intel_pinctrl *lg;
struct gpio_chip *gc;
struct resource *io_rc, *irq_rc;
struct device *dev = &pdev->dev;
void __iomem *regs;
unsigned int i;
int ret;
soc = (const struct intel_pinctrl_soc_data *)device_get_match_data(dev);
if (!soc)
return -ENODEV;
lg = devm_kzalloc(dev, sizeof(*lg), GFP_KERNEL);
if (!lg)
return -ENOMEM;
lg->dev = dev;
lg->soc = soc;
lg->ncommunities = lg->soc->ncommunities;
lg->communities = devm_kcalloc(dev, lg->ncommunities,
sizeof(*lg->communities), GFP_KERNEL);
if (!lg->communities)
return -ENOMEM;
lg->pctldesc = lptlp_pinctrl_desc;
lg->pctldesc.name = dev_name(dev);
lg->pctldesc.pins = lg->soc->pins;
lg->pctldesc.npins = lg->soc->npins;
lg->pctldev = devm_pinctrl_register(dev, &lg->pctldesc, lg);
if (IS_ERR(lg->pctldev)) {
dev_err(dev, "failed to register pinctrl driver\n");
return PTR_ERR(lg->pctldev);
}
platform_set_drvdata(pdev, lg);
io_rc = platform_get_resource(pdev, IORESOURCE_IO, 0);
if (!io_rc) {
dev_err(dev, "missing IO resources\n");
return -EINVAL;
}
regs = devm_ioport_map(dev, io_rc->start, resource_size(io_rc));
if (!regs) {
dev_err(dev, "failed mapping IO region %pR\n", &io_rc);
return -EBUSY;
}
for (i = 0; i < lg->soc->ncommunities; i++) {
struct intel_community *comm = &lg->communities[i];
*comm = lg->soc->communities[i];
comm->regs = regs;
comm->pad_regs = regs + 0x100;
}
raw_spin_lock_init(&lg->lock);
gc = &lg->chip;
gc->label = dev_name(dev);
gc->owner = THIS_MODULE;
gc->request = gpiochip_generic_request;
gc->free = gpiochip_generic_free;
gc->direction_input = lp_gpio_direction_input;
gc->direction_output = lp_gpio_direction_output;
gc->get = lp_gpio_get;
gc->set = lp_gpio_set;
gc->get_direction = lp_gpio_get_direction;
gc->base = -1;
gc->ngpio = LP_NUM_GPIO;
gc->can_sleep = false;
gc->add_pin_ranges = lp_gpio_add_pin_ranges;
gc->parent = dev;
/* set up interrupts */
irq_rc = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (irq_rc && irq_rc->start) {
struct gpio_irq_chip *girq;
girq = &gc->irq;
girq->chip = &lp_irqchip;
girq->init_hw = lp_gpio_irq_init_hw;
girq->parent_handler = lp_gpio_irq_handler;
girq->num_parents = 1;
girq->parents = devm_kcalloc(dev, girq->num_parents,
sizeof(*girq->parents),
GFP_KERNEL);
if (!girq->parents)
return -ENOMEM;
girq->parents[0] = (unsigned int)irq_rc->start;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_bad_irq;
}
ret = devm_gpiochip_add_data(dev, gc, lg);
if (ret) {
dev_err(dev, "failed adding lp-gpio chip\n");
return ret;
}
pm_runtime_enable(dev);
return 0;
}
static int lp_gpio_remove(struct platform_device *pdev)
{
pm_runtime_disable(&pdev->dev);
return 0;
}
static int lp_gpio_runtime_suspend(struct device *dev)
{
return 0;
}
static int lp_gpio_runtime_resume(struct device *dev)
{
return 0;
}
static int lp_gpio_resume(struct device *dev)
{
struct intel_pinctrl *lg = dev_get_drvdata(dev);
void __iomem *reg;
int i;
/* on some hardware suspend clears input sensing, re-enable it here */
for (i = 0; i < lg->chip.ngpio; i++) {
if (gpiochip_is_requested(&lg->chip, i) != NULL) {
reg = lp_gpio_reg(&lg->chip, i, LP_CONFIG2);
iowrite32(ioread32(reg) & ~GPINDIS_BIT, reg);
}
}
return 0;
}
static const struct dev_pm_ops lp_gpio_pm_ops = {
.runtime_suspend = lp_gpio_runtime_suspend,
.runtime_resume = lp_gpio_runtime_resume,
.resume = lp_gpio_resume,
};
static const struct acpi_device_id lynxpoint_gpio_acpi_match[] = {
{ "INT33C7", (kernel_ulong_t)&lptlp_soc_data },
{ "INT3437", (kernel_ulong_t)&lptlp_soc_data },
{ }
};
MODULE_DEVICE_TABLE(acpi, lynxpoint_gpio_acpi_match);
static struct platform_driver lp_gpio_driver = {
.probe = lp_gpio_probe,
.remove = lp_gpio_remove,
.driver = {
.name = "lp_gpio",
.pm = &lp_gpio_pm_ops,
.acpi_match_table = ACPI_PTR(lynxpoint_gpio_acpi_match),
},
};
static int __init lp_gpio_init(void)
{
return platform_driver_register(&lp_gpio_driver);
}
static void __exit lp_gpio_exit(void)
{
platform_driver_unregister(&lp_gpio_driver);
}
subsys_initcall(lp_gpio_init);
module_exit(lp_gpio_exit);
MODULE_AUTHOR("Mathias Nyman (Intel)");
MODULE_AUTHOR("Andy Shevchenko (Intel)");
MODULE_DESCRIPTION("Intel Lynxpoint pinctrl driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:lp_gpio");

View file

@ -49,6 +49,7 @@
.padown_offset = SPT_PAD_OWN, \
.padcfglock_offset = SPT_PADCFGLOCK, \
.hostown_offset = SPT_HOSTSW_OWN, \
.is_offset = SPT_GPI_IS, \
.ie_offset = SPT_GPI_IE, \
.pin_base = (s), \
.npins = ((e) - (s) + 1), \
@ -588,6 +589,7 @@ static const struct intel_pinctrl_soc_data spth_soc_data = {
static const struct acpi_device_id spt_pinctrl_acpi_match[] = {
{ "INT344B", (kernel_ulong_t)&sptlp_soc_data },
{ "INT3451", (kernel_ulong_t)&spth_soc_data },
{ "INT345D", (kernel_ulong_t)&spth_soc_data },
{ }
};

View file

@ -2,7 +2,7 @@
/*
* Intel Tiger Lake PCH pinctrl/GPIO driver
*
* Copyright (C) 2019, Intel Corporation
* Copyright (C) 2019 - 2020, Intel Corporation
* Authors: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
* Mika Westerberg <mika.westerberg@linux.intel.com>
*/
@ -21,15 +21,19 @@
#define TGL_GPI_IS 0x100
#define TGL_GPI_IE 0x120
#define TGL_GPP(r, s, e) \
#define TGL_NO_GPIO -1
#define TGL_GPP(r, s, e, g) \
{ \
.reg_num = (r), \
.base = (s), \
.size = ((e) - (s) + 1), \
.gpio_base = (g), \
}
#define TGL_COMMUNITY(s, e, g) \
#define TGL_COMMUNITY(b, s, e, g) \
{ \
.barno = (b), \
.padown_offset = TGL_PAD_OWN, \
.padcfglock_offset = TGL_PADCFGLOCK, \
.hostown_offset = TGL_HOSTSW_OWN, \
@ -42,7 +46,7 @@
}
/* Tiger Lake-LP */
static const struct pinctrl_pin_desc tgllp_community0_pins[] = {
static const struct pinctrl_pin_desc tgllp_pins[] = {
/* GPP_B */
PINCTRL_PIN(0, "CORE_VID_0"),
PINCTRL_PIN(1, "CORE_VID_1"),
@ -113,324 +117,273 @@ static const struct pinctrl_pin_desc tgllp_community0_pins[] = {
PINCTRL_PIN(64, "GPPC_A_22"),
PINCTRL_PIN(65, "I2S1_SCLK"),
PINCTRL_PIN(66, "ESPI_CLK_LOOPBK"),
/* GPP_S */
PINCTRL_PIN(67, "SNDW0_CLK"),
PINCTRL_PIN(68, "SNDW0_DATA"),
PINCTRL_PIN(69, "SNDW1_CLK"),
PINCTRL_PIN(70, "SNDW1_DATA"),
PINCTRL_PIN(71, "SNDW2_CLK"),
PINCTRL_PIN(72, "SNDW2_DATA"),
PINCTRL_PIN(73, "SNDW3_CLK"),
PINCTRL_PIN(74, "SNDW3_DATA"),
/* GPP_H */
PINCTRL_PIN(75, "GPPC_H_0"),
PINCTRL_PIN(76, "GPPC_H_1"),
PINCTRL_PIN(77, "GPPC_H_2"),
PINCTRL_PIN(78, "SX_EXIT_HOLDOFFB"),
PINCTRL_PIN(79, "I2C2_SDA"),
PINCTRL_PIN(80, "I2C2_SCL"),
PINCTRL_PIN(81, "I2C3_SDA"),
PINCTRL_PIN(82, "I2C3_SCL"),
PINCTRL_PIN(83, "I2C4_SDA"),
PINCTRL_PIN(84, "I2C4_SCL"),
PINCTRL_PIN(85, "SRCCLKREQB_4"),
PINCTRL_PIN(86, "SRCCLKREQB_5"),
PINCTRL_PIN(87, "M2_SKT2_CFG_0"),
PINCTRL_PIN(88, "M2_SKT2_CFG_1"),
PINCTRL_PIN(89, "M2_SKT2_CFG_2"),
PINCTRL_PIN(90, "M2_SKT2_CFG_3"),
PINCTRL_PIN(91, "DDPB_CTRLCLK"),
PINCTRL_PIN(92, "DDPB_CTRLDATA"),
PINCTRL_PIN(93, "CPU_C10_GATEB"),
PINCTRL_PIN(94, "TIME_SYNC_0"),
PINCTRL_PIN(95, "IMGCLKOUT_1"),
PINCTRL_PIN(96, "IMGCLKOUT_2"),
PINCTRL_PIN(97, "IMGCLKOUT_3"),
PINCTRL_PIN(98, "IMGCLKOUT_4"),
/* GPP_D */
PINCTRL_PIN(99, "ISH_GP_0"),
PINCTRL_PIN(100, "ISH_GP_1"),
PINCTRL_PIN(101, "ISH_GP_2"),
PINCTRL_PIN(102, "ISH_GP_3"),
PINCTRL_PIN(103, "IMGCLKOUT_0"),
PINCTRL_PIN(104, "SRCCLKREQB_0"),
PINCTRL_PIN(105, "SRCCLKREQB_1"),
PINCTRL_PIN(106, "SRCCLKREQB_2"),
PINCTRL_PIN(107, "SRCCLKREQB_3"),
PINCTRL_PIN(108, "ISH_SPI_CSB"),
PINCTRL_PIN(109, "ISH_SPI_CLK"),
PINCTRL_PIN(110, "ISH_SPI_MISO"),
PINCTRL_PIN(111, "ISH_SPI_MOSI"),
PINCTRL_PIN(112, "ISH_UART0_RXD"),
PINCTRL_PIN(113, "ISH_UART0_TXD"),
PINCTRL_PIN(114, "ISH_UART0_RTSB"),
PINCTRL_PIN(115, "ISH_UART0_CTSB"),
PINCTRL_PIN(116, "ISH_GP_4"),
PINCTRL_PIN(117, "ISH_GP_5"),
PINCTRL_PIN(118, "I2S_MCLK1_OUT"),
PINCTRL_PIN(119, "GSPI2_CLK_LOOPBK"),
/* GPP_U */
PINCTRL_PIN(120, "UART3_RXD"),
PINCTRL_PIN(121, "UART3_TXD"),
PINCTRL_PIN(122, "UART3_RTSB"),
PINCTRL_PIN(123, "UART3_CTSB"),
PINCTRL_PIN(124, "GSPI3_CS0B"),
PINCTRL_PIN(125, "GSPI3_CLK"),
PINCTRL_PIN(126, "GSPI3_MISO"),
PINCTRL_PIN(127, "GSPI3_MOSI"),
PINCTRL_PIN(128, "GSPI4_CS0B"),
PINCTRL_PIN(129, "GSPI4_CLK"),
PINCTRL_PIN(130, "GSPI4_MISO"),
PINCTRL_PIN(131, "GSPI4_MOSI"),
PINCTRL_PIN(132, "GSPI5_CS0B"),
PINCTRL_PIN(133, "GSPI5_CLK"),
PINCTRL_PIN(134, "GSPI5_MISO"),
PINCTRL_PIN(135, "GSPI5_MOSI"),
PINCTRL_PIN(136, "GSPI6_CS0B"),
PINCTRL_PIN(137, "GSPI6_CLK"),
PINCTRL_PIN(138, "GSPI6_MISO"),
PINCTRL_PIN(139, "GSPI6_MOSI"),
PINCTRL_PIN(140, "GSPI3_CLK_LOOPBK"),
PINCTRL_PIN(141, "GSPI4_CLK_LOOPBK"),
PINCTRL_PIN(142, "GSPI5_CLK_LOOPBK"),
PINCTRL_PIN(143, "GSPI6_CLK_LOOPBK"),
/* vGPIO */
PINCTRL_PIN(144, "CNV_BTEN"),
PINCTRL_PIN(145, "CNV_BT_HOST_WAKEB"),
PINCTRL_PIN(146, "CNV_BT_IF_SELECT"),
PINCTRL_PIN(147, "vCNV_BT_UART_TXD"),
PINCTRL_PIN(148, "vCNV_BT_UART_RXD"),
PINCTRL_PIN(149, "vCNV_BT_UART_CTS_B"),
PINCTRL_PIN(150, "vCNV_BT_UART_RTS_B"),
PINCTRL_PIN(151, "vCNV_MFUART1_TXD"),
PINCTRL_PIN(152, "vCNV_MFUART1_RXD"),
PINCTRL_PIN(153, "vCNV_MFUART1_CTS_B"),
PINCTRL_PIN(154, "vCNV_MFUART1_RTS_B"),
PINCTRL_PIN(155, "vUART0_TXD"),
PINCTRL_PIN(156, "vUART0_RXD"),
PINCTRL_PIN(157, "vUART0_CTS_B"),
PINCTRL_PIN(158, "vUART0_RTS_B"),
PINCTRL_PIN(159, "vISH_UART0_TXD"),
PINCTRL_PIN(160, "vISH_UART0_RXD"),
PINCTRL_PIN(161, "vISH_UART0_CTS_B"),
PINCTRL_PIN(162, "vISH_UART0_RTS_B"),
PINCTRL_PIN(163, "vCNV_BT_I2S_BCLK"),
PINCTRL_PIN(164, "vCNV_BT_I2S_WS_SYNC"),
PINCTRL_PIN(165, "vCNV_BT_I2S_SDO"),
PINCTRL_PIN(166, "vCNV_BT_I2S_SDI"),
PINCTRL_PIN(167, "vI2S2_SCLK"),
PINCTRL_PIN(168, "vI2S2_SFRM"),
PINCTRL_PIN(169, "vI2S2_TXD"),
PINCTRL_PIN(170, "vI2S2_RXD"),
/* GPP_C */
PINCTRL_PIN(171, "SMBCLK"),
PINCTRL_PIN(172, "SMBDATA"),
PINCTRL_PIN(173, "SMBALERTB"),
PINCTRL_PIN(174, "SML0CLK"),
PINCTRL_PIN(175, "SML0DATA"),
PINCTRL_PIN(176, "SML0ALERTB"),
PINCTRL_PIN(177, "SML1CLK"),
PINCTRL_PIN(178, "SML1DATA"),
PINCTRL_PIN(179, "UART0_RXD"),
PINCTRL_PIN(180, "UART0_TXD"),
PINCTRL_PIN(181, "UART0_RTSB"),
PINCTRL_PIN(182, "UART0_CTSB"),
PINCTRL_PIN(183, "UART1_RXD"),
PINCTRL_PIN(184, "UART1_TXD"),
PINCTRL_PIN(185, "UART1_RTSB"),
PINCTRL_PIN(186, "UART1_CTSB"),
PINCTRL_PIN(187, "I2C0_SDA"),
PINCTRL_PIN(188, "I2C0_SCL"),
PINCTRL_PIN(189, "I2C1_SDA"),
PINCTRL_PIN(190, "I2C1_SCL"),
PINCTRL_PIN(191, "UART2_RXD"),
PINCTRL_PIN(192, "UART2_TXD"),
PINCTRL_PIN(193, "UART2_RTSB"),
PINCTRL_PIN(194, "UART2_CTSB"),
/* GPP_F */
PINCTRL_PIN(195, "CNV_BRI_DT"),
PINCTRL_PIN(196, "CNV_BRI_RSP"),
PINCTRL_PIN(197, "CNV_RGI_DT"),
PINCTRL_PIN(198, "CNV_RGI_RSP"),
PINCTRL_PIN(199, "CNV_RF_RESET_B"),
PINCTRL_PIN(200, "GPPC_F_5"),
PINCTRL_PIN(201, "CNV_PA_BLANKING"),
PINCTRL_PIN(202, "GPPC_F_7"),
PINCTRL_PIN(203, "I2S_MCLK2_INOUT"),
PINCTRL_PIN(204, "BOOTMPC"),
PINCTRL_PIN(205, "GPPC_F_10"),
PINCTRL_PIN(206, "GPPC_F_11"),
PINCTRL_PIN(207, "GSXDOUT"),
PINCTRL_PIN(208, "GSXSLOAD"),
PINCTRL_PIN(209, "GSXDIN"),
PINCTRL_PIN(210, "GSXSRESETB"),
PINCTRL_PIN(211, "GSXCLK"),
PINCTRL_PIN(212, "GMII_MDC"),
PINCTRL_PIN(213, "GMII_MDIO"),
PINCTRL_PIN(214, "SRCCLKREQB_6"),
PINCTRL_PIN(215, "EXT_PWR_GATEB"),
PINCTRL_PIN(216, "EXT_PWR_GATE2B"),
PINCTRL_PIN(217, "VNN_CTRL"),
PINCTRL_PIN(218, "V1P05_CTRL"),
PINCTRL_PIN(219, "GPPF_CLK_LOOPBACK"),
/* HVCMOS */
PINCTRL_PIN(220, "L_BKLTEN"),
PINCTRL_PIN(221, "L_BKLTCTL"),
PINCTRL_PIN(222, "L_VDDEN"),
PINCTRL_PIN(223, "SYS_PWROK"),
PINCTRL_PIN(224, "SYS_RESETB"),
PINCTRL_PIN(225, "MLK_RSTB"),
/* GPP_E */
PINCTRL_PIN(226, "SATAXPCIE_0"),
PINCTRL_PIN(227, "SPI1_IO_2"),
PINCTRL_PIN(228, "SPI1_IO_3"),
PINCTRL_PIN(229, "CPU_GP_0"),
PINCTRL_PIN(230, "SATA_DEVSLP_0"),
PINCTRL_PIN(231, "SATA_DEVSLP_1"),
PINCTRL_PIN(232, "GPPC_E_6"),
PINCTRL_PIN(233, "CPU_GP_1"),
PINCTRL_PIN(234, "SPI1_CS1B"),
PINCTRL_PIN(235, "USB2_OCB_0"),
PINCTRL_PIN(236, "SPI1_CSB"),
PINCTRL_PIN(237, "SPI1_CLK"),
PINCTRL_PIN(238, "SPI1_MISO_IO_1"),
PINCTRL_PIN(239, "SPI1_MOSI_IO_0"),
PINCTRL_PIN(240, "DDSP_HPD_A"),
PINCTRL_PIN(241, "ISH_GP_6"),
PINCTRL_PIN(242, "ISH_GP_7"),
PINCTRL_PIN(243, "GPPC_E_17"),
PINCTRL_PIN(244, "DDP1_CTRLCLK"),
PINCTRL_PIN(245, "DDP1_CTRLDATA"),
PINCTRL_PIN(246, "DDP2_CTRLCLK"),
PINCTRL_PIN(247, "DDP2_CTRLDATA"),
PINCTRL_PIN(248, "DDPA_CTRLCLK"),
PINCTRL_PIN(249, "DDPA_CTRLDATA"),
PINCTRL_PIN(250, "SPI1_CLK_LOOPBK"),
/* JTAG */
PINCTRL_PIN(251, "JTAG_TDO"),
PINCTRL_PIN(252, "JTAGX"),
PINCTRL_PIN(253, "PRDYB"),
PINCTRL_PIN(254, "PREQB"),
PINCTRL_PIN(255, "CPU_TRSTB"),
PINCTRL_PIN(256, "JTAG_TDI"),
PINCTRL_PIN(257, "JTAG_TMS"),
PINCTRL_PIN(258, "JTAG_TCK"),
PINCTRL_PIN(259, "DBG_PMODE"),
/* GPP_R */
PINCTRL_PIN(260, "HDA_BCLK"),
PINCTRL_PIN(261, "HDA_SYNC"),
PINCTRL_PIN(262, "HDA_SDO"),
PINCTRL_PIN(263, "HDA_SDI_0"),
PINCTRL_PIN(264, "HDA_RSTB"),
PINCTRL_PIN(265, "HDA_SDI_1"),
PINCTRL_PIN(266, "GPP_R_6"),
PINCTRL_PIN(267, "GPP_R_7"),
/* SPI */
PINCTRL_PIN(268, "SPI0_IO_2"),
PINCTRL_PIN(269, "SPI0_IO_3"),
PINCTRL_PIN(270, "SPI0_MOSI_IO_0"),
PINCTRL_PIN(271, "SPI0_MISO_IO_1"),
PINCTRL_PIN(272, "SPI0_TPM_CSB"),
PINCTRL_PIN(273, "SPI0_FLASH_0_CSB"),
PINCTRL_PIN(274, "SPI0_FLASH_1_CSB"),
PINCTRL_PIN(275, "SPI0_CLK"),
PINCTRL_PIN(276, "SPI0_CLK_LOOPBK"),
};
static const struct intel_padgroup tgllp_community0_gpps[] = {
TGL_GPP(0, 0, 25), /* GPP_B */
TGL_GPP(1, 26, 41), /* GPP_T */
TGL_GPP(2, 42, 66), /* GPP_A */
};
static const struct intel_community tgllp_community0[] = {
TGL_COMMUNITY(0, 66, tgllp_community0_gpps),
};
static const struct intel_pinctrl_soc_data tgllp_community0_soc_data = {
.uid = "0",
.pins = tgllp_community0_pins,
.npins = ARRAY_SIZE(tgllp_community0_pins),
.communities = tgllp_community0,
.ncommunities = ARRAY_SIZE(tgllp_community0),
};
static const struct pinctrl_pin_desc tgllp_community1_pins[] = {
/* GPP_S */
PINCTRL_PIN(0, "SNDW0_CLK"),
PINCTRL_PIN(1, "SNDW0_DATA"),
PINCTRL_PIN(2, "SNDW1_CLK"),
PINCTRL_PIN(3, "SNDW1_DATA"),
PINCTRL_PIN(4, "SNDW2_CLK"),
PINCTRL_PIN(5, "SNDW2_DATA"),
PINCTRL_PIN(6, "SNDW3_CLK"),
PINCTRL_PIN(7, "SNDW3_DATA"),
/* GPP_H */
PINCTRL_PIN(8, "GPPC_H_0"),
PINCTRL_PIN(9, "GPPC_H_1"),
PINCTRL_PIN(10, "GPPC_H_2"),
PINCTRL_PIN(11, "SX_EXIT_HOLDOFFB"),
PINCTRL_PIN(12, "I2C2_SDA"),
PINCTRL_PIN(13, "I2C2_SCL"),
PINCTRL_PIN(14, "I2C3_SDA"),
PINCTRL_PIN(15, "I2C3_SCL"),
PINCTRL_PIN(16, "I2C4_SDA"),
PINCTRL_PIN(17, "I2C4_SCL"),
PINCTRL_PIN(18, "SRCCLKREQB_4"),
PINCTRL_PIN(19, "SRCCLKREQB_5"),
PINCTRL_PIN(20, "M2_SKT2_CFG_0"),
PINCTRL_PIN(21, "M2_SKT2_CFG_1"),
PINCTRL_PIN(22, "M2_SKT2_CFG_2"),
PINCTRL_PIN(23, "M2_SKT2_CFG_3"),
PINCTRL_PIN(24, "DDPB_CTRLCLK"),
PINCTRL_PIN(25, "DDPB_CTRLDATA"),
PINCTRL_PIN(26, "CPU_C10_GATEB"),
PINCTRL_PIN(27, "TIME_SYNC_0"),
PINCTRL_PIN(28, "IMGCLKOUT_1"),
PINCTRL_PIN(29, "IMGCLKOUT_2"),
PINCTRL_PIN(30, "IMGCLKOUT_3"),
PINCTRL_PIN(31, "IMGCLKOUT_4"),
/* GPP_D */
PINCTRL_PIN(32, "ISH_GP_0"),
PINCTRL_PIN(33, "ISH_GP_1"),
PINCTRL_PIN(34, "ISH_GP_2"),
PINCTRL_PIN(35, "ISH_GP_3"),
PINCTRL_PIN(36, "IMGCLKOUT_0"),
PINCTRL_PIN(37, "SRCCLKREQB_0"),
PINCTRL_PIN(38, "SRCCLKREQB_1"),
PINCTRL_PIN(39, "SRCCLKREQB_2"),
PINCTRL_PIN(40, "SRCCLKREQB_3"),
PINCTRL_PIN(41, "ISH_SPI_CSB"),
PINCTRL_PIN(42, "ISH_SPI_CLK"),
PINCTRL_PIN(43, "ISH_SPI_MISO"),
PINCTRL_PIN(44, "ISH_SPI_MOSI"),
PINCTRL_PIN(45, "ISH_UART0_RXD"),
PINCTRL_PIN(46, "ISH_UART0_TXD"),
PINCTRL_PIN(47, "ISH_UART0_RTSB"),
PINCTRL_PIN(48, "ISH_UART0_CTSB"),
PINCTRL_PIN(49, "ISH_GP_4"),
PINCTRL_PIN(50, "ISH_GP_5"),
PINCTRL_PIN(51, "I2S_MCLK1_OUT"),
PINCTRL_PIN(52, "GSPI2_CLK_LOOPBK"),
/* GPP_U */
PINCTRL_PIN(53, "UART3_RXD"),
PINCTRL_PIN(54, "UART3_TXD"),
PINCTRL_PIN(55, "UART3_RTSB"),
PINCTRL_PIN(56, "UART3_CTSB"),
PINCTRL_PIN(57, "GSPI3_CS0B"),
PINCTRL_PIN(58, "GSPI3_CLK"),
PINCTRL_PIN(59, "GSPI3_MISO"),
PINCTRL_PIN(60, "GSPI3_MOSI"),
PINCTRL_PIN(61, "GSPI4_CS0B"),
PINCTRL_PIN(62, "GSPI4_CLK"),
PINCTRL_PIN(63, "GSPI4_MISO"),
PINCTRL_PIN(64, "GSPI4_MOSI"),
PINCTRL_PIN(65, "GSPI5_CS0B"),
PINCTRL_PIN(66, "GSPI5_CLK"),
PINCTRL_PIN(67, "GSPI5_MISO"),
PINCTRL_PIN(68, "GSPI5_MOSI"),
PINCTRL_PIN(69, "GSPI6_CS0B"),
PINCTRL_PIN(70, "GSPI6_CLK"),
PINCTRL_PIN(71, "GSPI6_MISO"),
PINCTRL_PIN(72, "GSPI6_MOSI"),
PINCTRL_PIN(73, "GSPI3_CLK_LOOPBK"),
PINCTRL_PIN(74, "GSPI4_CLK_LOOPBK"),
PINCTRL_PIN(75, "GSPI5_CLK_LOOPBK"),
PINCTRL_PIN(76, "GSPI6_CLK_LOOPBK"),
/* vGPIO */
PINCTRL_PIN(77, "CNV_BTEN"),
PINCTRL_PIN(78, "CNV_BT_HOST_WAKEB"),
PINCTRL_PIN(79, "CNV_BT_IF_SELECT"),
PINCTRL_PIN(80, "vCNV_BT_UART_TXD"),
PINCTRL_PIN(81, "vCNV_BT_UART_RXD"),
PINCTRL_PIN(82, "vCNV_BT_UART_CTS_B"),
PINCTRL_PIN(83, "vCNV_BT_UART_RTS_B"),
PINCTRL_PIN(84, "vCNV_MFUART1_TXD"),
PINCTRL_PIN(85, "vCNV_MFUART1_RXD"),
PINCTRL_PIN(86, "vCNV_MFUART1_CTS_B"),
PINCTRL_PIN(87, "vCNV_MFUART1_RTS_B"),
PINCTRL_PIN(88, "vUART0_TXD"),
PINCTRL_PIN(89, "vUART0_RXD"),
PINCTRL_PIN(90, "vUART0_CTS_B"),
PINCTRL_PIN(91, "vUART0_RTS_B"),
PINCTRL_PIN(92, "vISH_UART0_TXD"),
PINCTRL_PIN(93, "vISH_UART0_RXD"),
PINCTRL_PIN(94, "vISH_UART0_CTS_B"),
PINCTRL_PIN(95, "vISH_UART0_RTS_B"),
PINCTRL_PIN(96, "vCNV_BT_I2S_BCLK"),
PINCTRL_PIN(97, "vCNV_BT_I2S_WS_SYNC"),
PINCTRL_PIN(98, "vCNV_BT_I2S_SDO"),
PINCTRL_PIN(99, "vCNV_BT_I2S_SDI"),
PINCTRL_PIN(100, "vI2S2_SCLK"),
PINCTRL_PIN(101, "vI2S2_SFRM"),
PINCTRL_PIN(102, "vI2S2_TXD"),
PINCTRL_PIN(103, "vI2S2_RXD"),
TGL_GPP(0, 0, 25, 0), /* GPP_B */
TGL_GPP(1, 26, 41, 32), /* GPP_T */
TGL_GPP(2, 42, 66, 64), /* GPP_A */
};
static const struct intel_padgroup tgllp_community1_gpps[] = {
TGL_GPP(0, 0, 7), /* GPP_S */
TGL_GPP(1, 8, 31), /* GPP_H */
TGL_GPP(2, 32, 52), /* GPP_D */
TGL_GPP(3, 53, 76), /* GPP_U */
TGL_GPP(4, 77, 103), /* vGPIO */
};
static const struct intel_community tgllp_community1[] = {
TGL_COMMUNITY(0, 103, tgllp_community1_gpps),
};
static const struct intel_pinctrl_soc_data tgllp_community1_soc_data = {
.uid = "1",
.pins = tgllp_community1_pins,
.npins = ARRAY_SIZE(tgllp_community1_pins),
.communities = tgllp_community1,
.ncommunities = ARRAY_SIZE(tgllp_community1),
};
static const struct pinctrl_pin_desc tgllp_community4_pins[] = {
/* GPP_C */
PINCTRL_PIN(0, "SMBCLK"),
PINCTRL_PIN(1, "SMBDATA"),
PINCTRL_PIN(2, "SMBALERTB"),
PINCTRL_PIN(3, "SML0CLK"),
PINCTRL_PIN(4, "SML0DATA"),
PINCTRL_PIN(5, "SML0ALERTB"),
PINCTRL_PIN(6, "SML1CLK"),
PINCTRL_PIN(7, "SML1DATA"),
PINCTRL_PIN(8, "UART0_RXD"),
PINCTRL_PIN(9, "UART0_TXD"),
PINCTRL_PIN(10, "UART0_RTSB"),
PINCTRL_PIN(11, "UART0_CTSB"),
PINCTRL_PIN(12, "UART1_RXD"),
PINCTRL_PIN(13, "UART1_TXD"),
PINCTRL_PIN(14, "UART1_RTSB"),
PINCTRL_PIN(15, "UART1_CTSB"),
PINCTRL_PIN(16, "I2C0_SDA"),
PINCTRL_PIN(17, "I2C0_SCL"),
PINCTRL_PIN(18, "I2C1_SDA"),
PINCTRL_PIN(19, "I2C1_SCL"),
PINCTRL_PIN(20, "UART2_RXD"),
PINCTRL_PIN(21, "UART2_TXD"),
PINCTRL_PIN(22, "UART2_RTSB"),
PINCTRL_PIN(23, "UART2_CTSB"),
/* GPP_F */
PINCTRL_PIN(24, "CNV_BRI_DT"),
PINCTRL_PIN(25, "CNV_BRI_RSP"),
PINCTRL_PIN(26, "CNV_RGI_DT"),
PINCTRL_PIN(27, "CNV_RGI_RSP"),
PINCTRL_PIN(28, "CNV_RF_RESET_B"),
PINCTRL_PIN(29, "GPPC_F_5"),
PINCTRL_PIN(30, "CNV_PA_BLANKING"),
PINCTRL_PIN(31, "GPPC_F_7"),
PINCTRL_PIN(32, "I2S_MCLK2_INOUT"),
PINCTRL_PIN(33, "BOOTMPC"),
PINCTRL_PIN(34, "GPPC_F_10"),
PINCTRL_PIN(35, "GPPC_F_11"),
PINCTRL_PIN(36, "GSXDOUT"),
PINCTRL_PIN(37, "GSXSLOAD"),
PINCTRL_PIN(38, "GSXDIN"),
PINCTRL_PIN(39, "GSXSRESETB"),
PINCTRL_PIN(40, "GSXCLK"),
PINCTRL_PIN(41, "GMII_MDC"),
PINCTRL_PIN(42, "GMII_MDIO"),
PINCTRL_PIN(43, "SRCCLKREQB_6"),
PINCTRL_PIN(44, "EXT_PWR_GATEB"),
PINCTRL_PIN(45, "EXT_PWR_GATE2B"),
PINCTRL_PIN(46, "VNN_CTRL"),
PINCTRL_PIN(47, "V1P05_CTRL"),
PINCTRL_PIN(48, "GPPF_CLK_LOOPBACK"),
/* HVCMOS */
PINCTRL_PIN(49, "L_BKLTEN"),
PINCTRL_PIN(50, "L_BKLTCTL"),
PINCTRL_PIN(51, "L_VDDEN"),
PINCTRL_PIN(52, "SYS_PWROK"),
PINCTRL_PIN(53, "SYS_RESETB"),
PINCTRL_PIN(54, "MLK_RSTB"),
/* GPP_E */
PINCTRL_PIN(55, "SATAXPCIE_0"),
PINCTRL_PIN(56, "SPI1_IO_2"),
PINCTRL_PIN(57, "SPI1_IO_3"),
PINCTRL_PIN(58, "CPU_GP_0"),
PINCTRL_PIN(59, "SATA_DEVSLP_0"),
PINCTRL_PIN(60, "SATA_DEVSLP_1"),
PINCTRL_PIN(61, "GPPC_E_6"),
PINCTRL_PIN(62, "CPU_GP_1"),
PINCTRL_PIN(63, "SPI1_CS1B"),
PINCTRL_PIN(64, "USB2_OCB_0"),
PINCTRL_PIN(65, "SPI1_CSB"),
PINCTRL_PIN(66, "SPI1_CLK"),
PINCTRL_PIN(67, "SPI1_MISO_IO_1"),
PINCTRL_PIN(68, "SPI1_MOSI_IO_0"),
PINCTRL_PIN(69, "DDSP_HPD_A"),
PINCTRL_PIN(70, "ISH_GP_6"),
PINCTRL_PIN(71, "ISH_GP_7"),
PINCTRL_PIN(72, "GPPC_E_17"),
PINCTRL_PIN(73, "DDP1_CTRLCLK"),
PINCTRL_PIN(74, "DDP1_CTRLDATA"),
PINCTRL_PIN(75, "DDP2_CTRLCLK"),
PINCTRL_PIN(76, "DDP2_CTRLDATA"),
PINCTRL_PIN(77, "DDPA_CTRLCLK"),
PINCTRL_PIN(78, "DDPA_CTRLDATA"),
PINCTRL_PIN(79, "SPI1_CLK_LOOPBK"),
/* JTAG */
PINCTRL_PIN(80, "JTAG_TDO"),
PINCTRL_PIN(81, "JTAGX"),
PINCTRL_PIN(82, "PRDYB"),
PINCTRL_PIN(83, "PREQB"),
PINCTRL_PIN(84, "CPU_TRSTB"),
PINCTRL_PIN(85, "JTAG_TDI"),
PINCTRL_PIN(86, "JTAG_TMS"),
PINCTRL_PIN(87, "JTAG_TCK"),
PINCTRL_PIN(88, "DBG_PMODE"),
TGL_GPP(0, 67, 74, 96), /* GPP_S */
TGL_GPP(1, 75, 98, 128), /* GPP_H */
TGL_GPP(2, 99, 119, 160), /* GPP_D */
TGL_GPP(3, 120, 143, 192), /* GPP_U */
TGL_GPP(4, 144, 170, 224), /* vGPIO */
};
static const struct intel_padgroup tgllp_community4_gpps[] = {
TGL_GPP(0, 0, 23), /* GPP_C */
TGL_GPP(1, 24, 48), /* GPP_F */
TGL_GPP(2, 49, 54), /* HVCMOS */
TGL_GPP(3, 55, 79), /* GPP_E */
TGL_GPP(4, 80, 88), /* JTAG */
};
static const struct intel_community tgllp_community4[] = {
TGL_COMMUNITY(0, 88, tgllp_community4_gpps),
};
static const struct intel_pinctrl_soc_data tgllp_community4_soc_data = {
.uid = "4",
.pins = tgllp_community4_pins,
.npins = ARRAY_SIZE(tgllp_community4_pins),
.communities = tgllp_community4,
.ncommunities = ARRAY_SIZE(tgllp_community4),
};
static const struct pinctrl_pin_desc tgllp_community5_pins[] = {
/* GPP_R */
PINCTRL_PIN(0, "HDA_BCLK"),
PINCTRL_PIN(1, "HDA_SYNC"),
PINCTRL_PIN(2, "HDA_SDO"),
PINCTRL_PIN(3, "HDA_SDI_0"),
PINCTRL_PIN(4, "HDA_RSTB"),
PINCTRL_PIN(5, "HDA_SDI_1"),
PINCTRL_PIN(6, "GPP_R_6"),
PINCTRL_PIN(7, "GPP_R_7"),
/* SPI */
PINCTRL_PIN(8, "SPI0_IO_2"),
PINCTRL_PIN(9, "SPI0_IO_3"),
PINCTRL_PIN(10, "SPI0_MOSI_IO_0"),
PINCTRL_PIN(11, "SPI0_MISO_IO_1"),
PINCTRL_PIN(12, "SPI0_TPM_CSB"),
PINCTRL_PIN(13, "SPI0_FLASH_0_CSB"),
PINCTRL_PIN(14, "SPI0_FLASH_1_CSB"),
PINCTRL_PIN(15, "SPI0_CLK"),
PINCTRL_PIN(16, "SPI0_CLK_LOOPBK"),
TGL_GPP(0, 171, 194, 256), /* GPP_C */
TGL_GPP(1, 195, 219, 288), /* GPP_F */
TGL_GPP(2, 220, 225, TGL_NO_GPIO), /* HVCMOS */
TGL_GPP(3, 226, 250, 320), /* GPP_E */
TGL_GPP(4, 251, 259, TGL_NO_GPIO), /* JTAG */
};
static const struct intel_padgroup tgllp_community5_gpps[] = {
TGL_GPP(0, 0, 7), /* GPP_R */
TGL_GPP(1, 8, 16), /* SPI */
TGL_GPP(0, 260, 267, 352), /* GPP_R */
TGL_GPP(1, 268, 276, TGL_NO_GPIO), /* SPI */
};
static const struct intel_community tgllp_community5[] = {
TGL_COMMUNITY(0, 16, tgllp_community5_gpps),
static const struct intel_community tgllp_communities[] = {
TGL_COMMUNITY(0, 0, 66, tgllp_community0_gpps),
TGL_COMMUNITY(1, 67, 170, tgllp_community1_gpps),
TGL_COMMUNITY(2, 171, 259, tgllp_community4_gpps),
TGL_COMMUNITY(3, 260, 276, tgllp_community5_gpps),
};
static const struct intel_pinctrl_soc_data tgllp_community5_soc_data = {
.uid = "5",
.pins = tgllp_community5_pins,
.npins = ARRAY_SIZE(tgllp_community5_pins),
.communities = tgllp_community5,
.ncommunities = ARRAY_SIZE(tgllp_community5),
};
static const struct intel_pinctrl_soc_data *tgllp_soc_data_array[] = {
&tgllp_community0_soc_data,
&tgllp_community1_soc_data,
&tgllp_community4_soc_data,
&tgllp_community5_soc_data,
NULL
static const struct intel_pinctrl_soc_data tgllp_soc_data = {
.pins = tgllp_pins,
.npins = ARRAY_SIZE(tgllp_pins),
.communities = tgllp_communities,
.ncommunities = ARRAY_SIZE(tgllp_communities),
};
static const struct acpi_device_id tgl_pinctrl_acpi_match[] = {
{ "INT34C5", (kernel_ulong_t)tgllp_soc_data_array },
{ "INT34C5", (kernel_ulong_t)&tgllp_soc_data },
{ }
};
MODULE_DEVICE_TABLE(acpi, tgl_pinctrl_acpi_match);
@ -438,7 +391,7 @@ MODULE_DEVICE_TABLE(acpi, tgl_pinctrl_acpi_match);
static INTEL_PINCTRL_PM_OPS(tgl_pinctrl_pm_ops);
static struct platform_driver tgl_pinctrl_driver = {
.probe = intel_pinctrl_probe_by_uid,
.probe = intel_pinctrl_probe_by_hid,
.driver = {
.name = "tigerlake-pinctrl",
.acpi_match_table = tgl_pinctrl_acpi_match,