intel-pinctrl for v6.6-1

* New library driver for Intel MID to deduplicate code (Raag Jadav)
 * Reuse common functions from pinctrl-intel to reduce the code (Raag Jadav)
 * Move most of the exported functions to the PINCTRL_INTEL namespace
 * Make use of pm_ptr() in Bay Trail and Lynxpoint drivers
 * Introduce DEFINE_NOIRQ_DEV_PM_OPS() helper and use it in a few drivers
 * Consolidata ACPI dependency in Kconfig (Raag Jadav)
 * Fix address_space_handler() argument in Cherryview driver (Raag Jadav)
 * Optinmize byt_pin_config_set() to avoid IO in error cases (Raag Jadav)
 
 The following is an automated git shortlog grouped by driver:
 
 at91:
  -  Switch to use DEFINE_NOIRQ_DEV_PM_OPS() helper
 
 baytrail:
  -  Make use of pm_ptr()
  -  reuse common functions from pinctrl-intel
  -  consolidate common mask operation
 
 cherryview:
  -  fix address_space_handler() argument
  -  Switch to use DEFINE_NOIRQ_DEV_PM_OPS() helper
  -  reuse common functions from pinctrl-intel
 
 intel:
  -  consolidate ACPI dependency
  -  Switch to use exported namespace
  -  export common pinctrl functions
 
 lynxpoint:
  -  Make use of pm_ptr()
  -  reuse common functions from pinctrl-intel
 
 Merge patch series:
  - Merge patch series "Introduce Intel Tangier pinctrl driver"
  - Merge patch series "Reuse common functions from pinctrl-intel"
 
 merrifield:
  -  Adapt to Intel Tangier driver
 
 moorefield:
  -  Adapt to Intel Tangier driver
 
 mvebu:
  -  Switch to use DEFINE_NOIRQ_DEV_PM_OPS() helper
 
 pm:
  -  Introduce DEFINE_NOIRQ_DEV_PM_OPS() helper
 
 renesas:
  -  Switch to use DEFINE_NOIRQ_DEV_PM_OPS() helper
 
 tangier:
  -  Introduce Intel Tangier driver
 
 tegra:
  -  Switch to use DEFINE_NOIRQ_DEV_PM_OPS() helper
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEqaflIX74DDDzMJJtb7wzTHR8rCgFAmTnJ9gACgkQb7wzTHR8
 rCh68A/+I+5GVamgfQV6ef9diFgTJQ1AVqarb0noeoKwwwv+LZRmUOdlS6ZAzuK8
 4LGVboIfrUcJ7pz0hiPbFZj4DvNnODTAPl+ZnaQd9n7H709sPvhlay1sK91TR1SB
 IjE7kmYrygswL7ufbDuhXEay4VGEKeR1pylbNI6Bi17kp7odio50O5o+ORvc/c5c
 Ho49EtMLraAxtTw1ZiojJ+shv27UM/Zit+EkddJOG+z6ORvlypymCiNToMgdxVfp
 rEqshWfJyjW2ucrF+KXAAUEKSTTxATKj+7gJO8l4r0lTZ8wEHo0Kh72JYVF4alnn
 G61ZjKjNwtGzQy7BkIzcY6gKByF297JW4pxeetBr2v0gRpwjwAqVfE9i2MoNB/Su
 W+yTEaz5TeAwoQ8HRgpaxYb503Y6bOnXETvn40QadewBqOr4G0/pxrTEqtDN6KzF
 rZIqs9/CpNl8HAH2HSW5qkxTC3efQAdHG6Df76Vu9WSzPRzMqJedrR4RTJoYd/1k
 MBHbN7Ur9/Bu93jwG71nbcLEz0DTvsmaM9N1ArTqc/GDZVf4ptUMGYtFsFcURt0C
 vj4cb+NaMI49VEAcJiWB7u6EqiWLDP7AhNbm9so4g7NGi0vVrrxZV7VCfsKC6Xmg
 XorgPN7hB9PxJ5K6xVWZi5wrIG3vcheF8U8v4wcj4IfkIny9ya0=
 =Jpna
 -----END PGP SIGNATURE-----

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

intel-pinctrl for v6.6-1

* New library driver for Intel MID to deduplicate code (Raag Jadav)
* Reuse common functions from pinctrl-intel to reduce the code (Raag Jadav)
* Move most of the exported functions to the PINCTRL_INTEL namespace
* Make use of pm_ptr() in Bay Trail and Lynxpoint drivers
* Introduce DEFINE_NOIRQ_DEV_PM_OPS() helper and use it in a few drivers
* Consolidata ACPI dependency in Kconfig (Raag Jadav)
* Fix address_space_handler() argument in Cherryview driver (Raag Jadav)
* Optinmize byt_pin_config_set() to avoid IO in error cases (Raag Jadav)

The following is an automated git shortlog grouped by driver:

at91:
 -  Switch to use DEFINE_NOIRQ_DEV_PM_OPS() helper

baytrail:
 -  Make use of pm_ptr()
 -  reuse common functions from pinctrl-intel
 -  consolidate common mask operation

cherryview:
 -  fix address_space_handler() argument
 -  Switch to use DEFINE_NOIRQ_DEV_PM_OPS() helper
 -  reuse common functions from pinctrl-intel

intel:
 -  consolidate ACPI dependency
 -  Switch to use exported namespace
 -  export common pinctrl functions

lynxpoint:
 -  Make use of pm_ptr()
 -  reuse common functions from pinctrl-intel

Merge patch series:
 - Merge patch series "Introduce Intel Tangier pinctrl driver"
 - Merge patch series "Reuse common functions from pinctrl-intel"

merrifield:
 -  Adapt to Intel Tangier driver

moorefield:
 -  Adapt to Intel Tangier driver

mvebu:
 -  Switch to use DEFINE_NOIRQ_DEV_PM_OPS() helper

pm:
 -  Introduce DEFINE_NOIRQ_DEV_PM_OPS() helper

renesas:
 -  Switch to use DEFINE_NOIRQ_DEV_PM_OPS() helper

tangier:
 -  Introduce Intel Tangier driver

tegra:
 -  Switch to use DEFINE_NOIRQ_DEV_PM_OPS() helper

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
Linus Walleij 2023-08-25 15:47:18 +02:00
commit 82a65f0844
33 changed files with 905 additions and 1613 deletions

View File

@ -1,11 +1,10 @@
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
# Intel pin control drivers # Intel pin control drivers
menu "Intel pinctrl drivers" menu "Intel pinctrl drivers"
depends on X86 || COMPILE_TEST depends on ACPI && (X86 || COMPILE_TEST)
config PINCTRL_BAYTRAIL config PINCTRL_BAYTRAIL
bool "Intel Baytrail GPIO pin control" bool "Intel Baytrail GPIO pin control"
depends on ACPI
select PINCTRL_INTEL select PINCTRL_INTEL
help help
driver for memory mapped GPIO functionality on Intel Baytrail driver for memory mapped GPIO functionality on Intel Baytrail
@ -17,7 +16,6 @@ config PINCTRL_BAYTRAIL
config PINCTRL_CHERRYVIEW config PINCTRL_CHERRYVIEW
tristate "Intel Cherryview/Braswell pinctrl and GPIO driver" tristate "Intel Cherryview/Braswell pinctrl and GPIO driver"
depends on ACPI
select PINCTRL_INTEL select PINCTRL_INTEL
help help
Cherryview/Braswell pinctrl driver provides an interface that Cherryview/Braswell pinctrl driver provides an interface that
@ -25,39 +23,12 @@ config PINCTRL_CHERRYVIEW
config PINCTRL_LYNXPOINT config PINCTRL_LYNXPOINT
tristate "Intel Lynxpoint pinctrl and GPIO driver" tristate "Intel Lynxpoint pinctrl and GPIO driver"
depends on ACPI select PINCTRL_INTEL
select PINMUX
select PINCONF
select GENERIC_PINCONF
select GPIOLIB
select GPIOLIB_IRQCHIP
help help
Lynxpoint is the PCH of Intel Haswell. This pinctrl driver Lynxpoint is the PCH of Intel Haswell. This pinctrl driver
provides an interface that allows configuring of PCH pins and provides an interface that allows configuring of PCH pins and
using them as GPIOs. using them as GPIOs.
config PINCTRL_MERRIFIELD
tristate "Intel Merrifield pinctrl driver"
depends on X86_INTEL_MID
select PINMUX
select PINCONF
select GENERIC_PINCONF
help
Merrifield Family-Level Interface Shim (FLIS) driver provides an
interface that allows configuring of SoC pins and using them as
GPIOs.
config PINCTRL_MOOREFIELD
tristate "Intel Moorefield pinctrl driver"
depends on X86_INTEL_MID
select PINMUX
select PINCONF
select GENERIC_PINCONF
help
Moorefield Family-Level Interface Shim (FLIS) driver provides an
interface that allows configuring of SoC pins and using them as
GPIOs.
config PINCTRL_INTEL config PINCTRL_INTEL
tristate tristate
select PINMUX select PINMUX
@ -68,7 +39,6 @@ config PINCTRL_INTEL
config PINCTRL_ALDERLAKE config PINCTRL_ALDERLAKE
tristate "Intel Alder Lake pinctrl and GPIO driver" tristate "Intel Alder Lake pinctrl and GPIO driver"
depends on ACPI
select PINCTRL_INTEL select PINCTRL_INTEL
help help
This pinctrl driver provides an interface that allows configuring This pinctrl driver provides an interface that allows configuring
@ -76,7 +46,6 @@ config PINCTRL_ALDERLAKE
config PINCTRL_BROXTON config PINCTRL_BROXTON
tristate "Intel Broxton pinctrl and GPIO driver" tristate "Intel Broxton pinctrl and GPIO driver"
depends on ACPI
select PINCTRL_INTEL select PINCTRL_INTEL
help help
Broxton pinctrl driver provides an interface that allows Broxton pinctrl driver provides an interface that allows
@ -84,7 +53,6 @@ config PINCTRL_BROXTON
config PINCTRL_CANNONLAKE config PINCTRL_CANNONLAKE
tristate "Intel Cannon Lake PCH pinctrl and GPIO driver" tristate "Intel Cannon Lake PCH pinctrl and GPIO driver"
depends on ACPI
select PINCTRL_INTEL select PINCTRL_INTEL
help help
This pinctrl driver provides an interface that allows configuring This pinctrl driver provides an interface that allows configuring
@ -92,7 +60,6 @@ config PINCTRL_CANNONLAKE
config PINCTRL_CEDARFORK config PINCTRL_CEDARFORK
tristate "Intel Cedar Fork pinctrl and GPIO driver" tristate "Intel Cedar Fork pinctrl and GPIO driver"
depends on ACPI
select PINCTRL_INTEL select PINCTRL_INTEL
help help
This pinctrl driver provides an interface that allows configuring This pinctrl driver provides an interface that allows configuring
@ -100,7 +67,6 @@ config PINCTRL_CEDARFORK
config PINCTRL_DENVERTON config PINCTRL_DENVERTON
tristate "Intel Denverton pinctrl and GPIO driver" tristate "Intel Denverton pinctrl and GPIO driver"
depends on ACPI
select PINCTRL_INTEL select PINCTRL_INTEL
help help
This pinctrl driver provides an interface that allows configuring This pinctrl driver provides an interface that allows configuring
@ -108,7 +74,6 @@ config PINCTRL_DENVERTON
config PINCTRL_ELKHARTLAKE config PINCTRL_ELKHARTLAKE
tristate "Intel Elkhart Lake SoC pinctrl and GPIO driver" tristate "Intel Elkhart Lake SoC pinctrl and GPIO driver"
depends on ACPI
select PINCTRL_INTEL select PINCTRL_INTEL
help help
This pinctrl driver provides an interface that allows configuring This pinctrl driver provides an interface that allows configuring
@ -116,7 +81,6 @@ config PINCTRL_ELKHARTLAKE
config PINCTRL_EMMITSBURG config PINCTRL_EMMITSBURG
tristate "Intel Emmitsburg pinctrl and GPIO driver" tristate "Intel Emmitsburg pinctrl and GPIO driver"
depends on ACPI
select PINCTRL_INTEL select PINCTRL_INTEL
help help
This pinctrl driver provides an interface that allows configuring This pinctrl driver provides an interface that allows configuring
@ -124,7 +88,6 @@ config PINCTRL_EMMITSBURG
config PINCTRL_GEMINILAKE config PINCTRL_GEMINILAKE
tristate "Intel Gemini Lake SoC pinctrl and GPIO driver" tristate "Intel Gemini Lake SoC pinctrl and GPIO driver"
depends on ACPI
select PINCTRL_INTEL select PINCTRL_INTEL
help help
This pinctrl driver provides an interface that allows configuring This pinctrl driver provides an interface that allows configuring
@ -132,7 +95,6 @@ config PINCTRL_GEMINILAKE
config PINCTRL_ICELAKE config PINCTRL_ICELAKE
tristate "Intel Ice Lake PCH pinctrl and GPIO driver" tristate "Intel Ice Lake PCH pinctrl and GPIO driver"
depends on ACPI
select PINCTRL_INTEL select PINCTRL_INTEL
help help
This pinctrl driver provides an interface that allows configuring This pinctrl driver provides an interface that allows configuring
@ -140,7 +102,6 @@ config PINCTRL_ICELAKE
config PINCTRL_JASPERLAKE config PINCTRL_JASPERLAKE
tristate "Intel Jasper Lake PCH pinctrl and GPIO driver" tristate "Intel Jasper Lake PCH pinctrl and GPIO driver"
depends on ACPI
select PINCTRL_INTEL select PINCTRL_INTEL
help help
This pinctrl driver provides an interface that allows configuring This pinctrl driver provides an interface that allows configuring
@ -148,7 +109,6 @@ config PINCTRL_JASPERLAKE
config PINCTRL_LAKEFIELD config PINCTRL_LAKEFIELD
tristate "Intel Lakefield SoC pinctrl and GPIO driver" tristate "Intel Lakefield SoC pinctrl and GPIO driver"
depends on ACPI
select PINCTRL_INTEL select PINCTRL_INTEL
help help
This pinctrl driver provides an interface that allows configuring This pinctrl driver provides an interface that allows configuring
@ -156,7 +116,6 @@ config PINCTRL_LAKEFIELD
config PINCTRL_LEWISBURG config PINCTRL_LEWISBURG
tristate "Intel Lewisburg pinctrl and GPIO driver" tristate "Intel Lewisburg pinctrl and GPIO driver"
depends on ACPI
select PINCTRL_INTEL select PINCTRL_INTEL
help help
This pinctrl driver provides an interface that allows configuring This pinctrl driver provides an interface that allows configuring
@ -164,7 +123,6 @@ config PINCTRL_LEWISBURG
config PINCTRL_METEORLAKE config PINCTRL_METEORLAKE
tristate "Intel Meteor Lake pinctrl and GPIO driver" tristate "Intel Meteor Lake pinctrl and GPIO driver"
depends on ACPI
select PINCTRL_INTEL select PINCTRL_INTEL
help help
This pinctrl driver provides an interface that allows configuring This pinctrl driver provides an interface that allows configuring
@ -172,7 +130,6 @@ config PINCTRL_METEORLAKE
config PINCTRL_SUNRISEPOINT config PINCTRL_SUNRISEPOINT
tristate "Intel Sunrisepoint pinctrl and GPIO driver" tristate "Intel Sunrisepoint pinctrl and GPIO driver"
depends on ACPI
select PINCTRL_INTEL select PINCTRL_INTEL
help help
Sunrisepoint is the PCH of Intel Skylake. This pinctrl driver Sunrisepoint is the PCH of Intel Skylake. This pinctrl driver
@ -181,10 +138,10 @@ config PINCTRL_SUNRISEPOINT
config PINCTRL_TIGERLAKE config PINCTRL_TIGERLAKE
tristate "Intel Tiger Lake pinctrl and GPIO driver" tristate "Intel Tiger Lake pinctrl and GPIO driver"
depends on ACPI
select PINCTRL_INTEL select PINCTRL_INTEL
help help
This pinctrl driver provides an interface that allows configuring This pinctrl driver provides an interface that allows configuring
of Intel Tiger Lake PCH pins and using them as GPIOs. of Intel Tiger Lake PCH pins and using them as GPIOs.
source "drivers/pinctrl/intel/Kconfig.tng"
endmenu endmenu

View File

@ -0,0 +1,33 @@
# SPDX-License-Identifier: GPL-2.0-only
# Intel Tangier and compatible pin control drivers
if X86_INTEL_MID || COMPILE_TEST
config PINCTRL_TANGIER
tristate
select PINMUX
select PINCONF
select GENERIC_PINCONF
help
This is a library driver for Intel Tangier pin controller and to
be selected and used by respective compatible platform drivers.
If built as a module its name will be pinctrl-tangier.
config PINCTRL_MERRIFIELD
tristate "Intel Merrifield pinctrl driver"
select PINCTRL_TANGIER
help
Intel Merrifield Family-Level Interface Shim (FLIS) driver provides
an interface that allows configuring of SoC pins and using them as
GPIOs.
config PINCTRL_MOOREFIELD
tristate "Intel Moorefield pinctrl driver"
select PINCTRL_TANGIER
help
Intel Moorefield Family-Level Interface Shim (FLIS) driver provides
an interface that allows configuring of SoC pins and using them as
GPIOs.
endif

View File

@ -4,6 +4,7 @@
obj-$(CONFIG_PINCTRL_BAYTRAIL) += pinctrl-baytrail.o obj-$(CONFIG_PINCTRL_BAYTRAIL) += pinctrl-baytrail.o
obj-$(CONFIG_PINCTRL_CHERRYVIEW) += pinctrl-cherryview.o obj-$(CONFIG_PINCTRL_CHERRYVIEW) += pinctrl-cherryview.o
obj-$(CONFIG_PINCTRL_LYNXPOINT) += pinctrl-lynxpoint.o obj-$(CONFIG_PINCTRL_LYNXPOINT) += pinctrl-lynxpoint.o
obj-$(CONFIG_PINCTRL_TANGIER) += pinctrl-tangier.o
obj-$(CONFIG_PINCTRL_MERRIFIELD) += pinctrl-merrifield.o obj-$(CONFIG_PINCTRL_MERRIFIELD) += pinctrl-merrifield.o
obj-$(CONFIG_PINCTRL_MOOREFIELD) += pinctrl-moorefield.o obj-$(CONFIG_PINCTRL_MOOREFIELD) += pinctrl-moorefield.o
obj-$(CONFIG_PINCTRL_INTEL) += pinctrl-intel.o obj-$(CONFIG_PINCTRL_INTEL) += pinctrl-intel.o

View File

@ -748,3 +748,4 @@ module_platform_driver(adl_pinctrl_driver);
MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>"); MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
MODULE_DESCRIPTION("Intel Alder Lake PCH pinctrl/GPIO driver"); MODULE_DESCRIPTION("Intel Alder Lake PCH pinctrl/GPIO driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_IMPORT_NS(PINCTRL_INTEL);

View File

@ -13,6 +13,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
@ -551,25 +552,10 @@ static const struct intel_pinctrl_soc_data *byt_soc_data[] = {
static DEFINE_RAW_SPINLOCK(byt_lock); static DEFINE_RAW_SPINLOCK(byt_lock);
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->ncommunities; i++) {
comm = vg->communities + i;
if (pin < comm->pin_base + comm->npins && pin >= comm->pin_base)
return comm;
}
return NULL;
}
static void __iomem *byt_gpio_reg(struct intel_pinctrl *vg, unsigned int offset, static void __iomem *byt_gpio_reg(struct intel_pinctrl *vg, unsigned int offset,
int reg) int reg)
{ {
struct intel_community *comm = byt_get_community(vg, offset); struct intel_community *comm = intel_get_community(vg, offset);
u32 reg_offset; u32 reg_offset;
if (!comm) if (!comm)
@ -591,68 +577,12 @@ static void __iomem *byt_gpio_reg(struct intel_pinctrl *vg, unsigned int offset,
return comm->pad_regs + reg_offset + reg; return comm->pad_regs + reg_offset + reg;
} }
static int byt_get_groups_count(struct pinctrl_dev *pctldev)
{
struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctldev);
return vg->soc->ngroups;
}
static const char *byt_get_group_name(struct pinctrl_dev *pctldev,
unsigned int selector)
{
struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctldev);
return vg->soc->groups[selector].grp.name;
}
static int byt_get_group_pins(struct pinctrl_dev *pctldev,
unsigned int selector,
const unsigned int **pins,
unsigned int *num_pins)
{
struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctldev);
*pins = vg->soc->groups[selector].grp.pins;
*num_pins = vg->soc->groups[selector].grp.npins;
return 0;
}
static const struct pinctrl_ops byt_pinctrl_ops = { static const struct pinctrl_ops byt_pinctrl_ops = {
.get_groups_count = byt_get_groups_count, .get_groups_count = intel_get_groups_count,
.get_group_name = byt_get_group_name, .get_group_name = intel_get_group_name,
.get_group_pins = byt_get_group_pins, .get_group_pins = intel_get_group_pins,
}; };
static int byt_get_functions_count(struct pinctrl_dev *pctldev)
{
struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctldev);
return vg->soc->nfunctions;
}
static const char *byt_get_function_name(struct pinctrl_dev *pctldev,
unsigned int selector)
{
struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctldev);
return vg->soc->functions[selector].func.name;
}
static int byt_get_function_groups(struct pinctrl_dev *pctldev,
unsigned int selector,
const char * const **groups,
unsigned int *ngroups)
{
struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctldev);
*groups = vg->soc->functions[selector].func.groups;
*ngroups = vg->soc->functions[selector].func.ngroups;
return 0;
}
static void byt_set_group_simple_mux(struct intel_pinctrl *vg, static void byt_set_group_simple_mux(struct intel_pinctrl *vg,
const struct intel_pingroup group, const struct intel_pingroup group,
unsigned int func) unsigned int func)
@ -851,9 +781,9 @@ static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev,
} }
static const struct pinmux_ops byt_pinmux_ops = { static const struct pinmux_ops byt_pinmux_ops = {
.get_functions_count = byt_get_functions_count, .get_functions_count = intel_get_functions_count,
.get_function_name = byt_get_function_name, .get_function_name = intel_get_function_name,
.get_function_groups = byt_get_function_groups, .get_function_groups = intel_get_function_groups,
.set_mux = byt_set_mux, .set_mux = byt_set_mux,
.gpio_request_enable = byt_gpio_request_enable, .gpio_request_enable = byt_gpio_request_enable,
.gpio_disable_free = byt_gpio_disable_free, .gpio_disable_free = byt_gpio_disable_free,
@ -995,8 +925,8 @@ static int byt_pin_config_set(struct pinctrl_dev *pctl_dev,
void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG); void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG); void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
void __iomem *db_reg = byt_gpio_reg(vg, offset, BYT_DEBOUNCE_REG); void __iomem *db_reg = byt_gpio_reg(vg, offset, BYT_DEBOUNCE_REG);
u32 conf, val, db_pulse, debounce;
unsigned long flags; unsigned long flags;
u32 conf, val, debounce;
int i, ret = 0; int i, ret = 0;
raw_spin_lock_irqsave(&byt_lock, flags); raw_spin_lock_irqsave(&byt_lock, flags);
@ -1053,8 +983,6 @@ static int byt_pin_config_set(struct pinctrl_dev *pctl_dev,
break; break;
case PIN_CONFIG_INPUT_DEBOUNCE: case PIN_CONFIG_INPUT_DEBOUNCE:
debounce = readl(db_reg);
if (arg) if (arg)
conf |= BYT_DEBOUNCE_EN; conf |= BYT_DEBOUNCE_EN;
else else
@ -1062,32 +990,25 @@ static int byt_pin_config_set(struct pinctrl_dev *pctl_dev,
switch (arg) { switch (arg) {
case 375: case 375:
debounce &= ~BYT_DEBOUNCE_PULSE_MASK; db_pulse = BYT_DEBOUNCE_PULSE_375US;
debounce |= BYT_DEBOUNCE_PULSE_375US;
break; break;
case 750: case 750:
debounce &= ~BYT_DEBOUNCE_PULSE_MASK; db_pulse = BYT_DEBOUNCE_PULSE_750US;
debounce |= BYT_DEBOUNCE_PULSE_750US;
break; break;
case 1500: case 1500:
debounce &= ~BYT_DEBOUNCE_PULSE_MASK; db_pulse = BYT_DEBOUNCE_PULSE_1500US;
debounce |= BYT_DEBOUNCE_PULSE_1500US;
break; break;
case 3000: case 3000:
debounce &= ~BYT_DEBOUNCE_PULSE_MASK; db_pulse = BYT_DEBOUNCE_PULSE_3MS;
debounce |= BYT_DEBOUNCE_PULSE_3MS;
break; break;
case 6000: case 6000:
debounce &= ~BYT_DEBOUNCE_PULSE_MASK; db_pulse = BYT_DEBOUNCE_PULSE_6MS;
debounce |= BYT_DEBOUNCE_PULSE_6MS;
break; break;
case 12000: case 12000:
debounce &= ~BYT_DEBOUNCE_PULSE_MASK; db_pulse = BYT_DEBOUNCE_PULSE_12MS;
debounce |= BYT_DEBOUNCE_PULSE_12MS;
break; break;
case 24000: case 24000:
debounce &= ~BYT_DEBOUNCE_PULSE_MASK; db_pulse = BYT_DEBOUNCE_PULSE_24MS;
debounce |= BYT_DEBOUNCE_PULSE_24MS;
break; break;
default: default:
if (arg) if (arg)
@ -1095,8 +1016,13 @@ static int byt_pin_config_set(struct pinctrl_dev *pctl_dev,
break; break;
} }
if (!ret) if (ret)
writel(debounce, db_reg); break;
debounce = readl(db_reg);
debounce = (debounce & ~BYT_DEBOUNCE_PULSE_MASK) | db_pulse;
writel(debounce, db_reg);
break; break;
default: default:
ret = -ENOTSUPP; ret = -ENOTSUPP;
@ -1265,7 +1191,7 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
val = readl(val_reg); val = readl(val_reg);
raw_spin_unlock_irqrestore(&byt_lock, flags); raw_spin_unlock_irqrestore(&byt_lock, flags);
comm = byt_get_community(vg, pin); comm = intel_get_community(vg, pin);
if (!comm) { if (!comm) {
seq_printf(s, "Pin %i: can't retrieve community\n", pin); seq_printf(s, "Pin %i: can't retrieve community\n", pin);
continue; continue;
@ -1733,7 +1659,6 @@ static int byt_pinctrl_probe(struct platform_device *pdev)
return 0; return 0;
} }
#ifdef CONFIG_PM_SLEEP
static int byt_gpio_suspend(struct device *dev) static int byt_gpio_suspend(struct device *dev)
{ {
struct intel_pinctrl *vg = dev_get_drvdata(dev); struct intel_pinctrl *vg = dev_get_drvdata(dev);
@ -1817,9 +1742,7 @@ static int byt_gpio_resume(struct device *dev)
raw_spin_unlock_irqrestore(&byt_lock, flags); raw_spin_unlock_irqrestore(&byt_lock, flags);
return 0; return 0;
} }
#endif
#ifdef CONFIG_PM
static int byt_gpio_runtime_suspend(struct device *dev) static int byt_gpio_runtime_suspend(struct device *dev)
{ {
return 0; return 0;
@ -1829,19 +1752,17 @@ static int byt_gpio_runtime_resume(struct device *dev)
{ {
return 0; return 0;
} }
#endif
static const struct dev_pm_ops byt_gpio_pm_ops = { static const struct dev_pm_ops byt_gpio_pm_ops = {
SET_LATE_SYSTEM_SLEEP_PM_OPS(byt_gpio_suspend, byt_gpio_resume) LATE_SYSTEM_SLEEP_PM_OPS(byt_gpio_suspend, byt_gpio_resume)
SET_RUNTIME_PM_OPS(byt_gpio_runtime_suspend, byt_gpio_runtime_resume, RUNTIME_PM_OPS(byt_gpio_runtime_suspend, byt_gpio_runtime_resume, NULL)
NULL)
}; };
static struct platform_driver byt_gpio_driver = { static struct platform_driver byt_gpio_driver = {
.probe = byt_pinctrl_probe, .probe = byt_pinctrl_probe,
.driver = { .driver = {
.name = "byt_gpio", .name = "byt_gpio",
.pm = &byt_gpio_pm_ops, .pm = pm_ptr(&byt_gpio_pm_ops),
.acpi_match_table = byt_gpio_acpi_match, .acpi_match_table = byt_gpio_acpi_match,
.suppress_bind_attrs = true, .suppress_bind_attrs = true,
}, },
@ -1852,3 +1773,5 @@ static int __init byt_gpio_init(void)
return platform_driver_register(&byt_gpio_driver); return platform_driver_register(&byt_gpio_driver);
} }
subsys_initcall(byt_gpio_init); subsys_initcall(byt_gpio_init);
MODULE_IMPORT_NS(PINCTRL_INTEL);

View File

@ -1028,3 +1028,4 @@ MODULE_DESCRIPTION("Intel Broxton SoC pinctrl/GPIO driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:apollolake-pinctrl"); MODULE_ALIAS("platform:apollolake-pinctrl");
MODULE_ALIAS("platform:broxton-pinctrl"); MODULE_ALIAS("platform:broxton-pinctrl");
MODULE_IMPORT_NS(PINCTRL_INTEL);

View File

@ -834,9 +834,9 @@ static struct platform_driver cnl_pinctrl_driver = {
.pm = &cnl_pinctrl_pm_ops, .pm = &cnl_pinctrl_pm_ops,
}, },
}; };
module_platform_driver(cnl_pinctrl_driver); module_platform_driver(cnl_pinctrl_driver);
MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>"); MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
MODULE_DESCRIPTION("Intel Cannon Lake PCH pinctrl/GPIO driver"); MODULE_DESCRIPTION("Intel Cannon Lake PCH pinctrl/GPIO driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_IMPORT_NS(PINCTRL_INTEL);

View File

@ -351,3 +351,4 @@ module_exit(cdf_pinctrl_exit);
MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>"); MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
MODULE_DESCRIPTION("Intel Cedar Fork PCH pinctrl/GPIO driver"); MODULE_DESCRIPTION("Intel Cedar Fork PCH pinctrl/GPIO driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_IMPORT_NS(PINCTRL_INTEL);

View File

@ -617,31 +617,6 @@ static bool chv_pad_locked(struct intel_pinctrl *pctrl, unsigned int offset)
return chv_readl(pctrl, offset, CHV_PADCTRL1) & CHV_PADCTRL1_CFGLOCK; return chv_readl(pctrl, offset, CHV_PADCTRL1) & CHV_PADCTRL1_CFGLOCK;
} }
static int chv_get_groups_count(struct pinctrl_dev *pctldev)
{
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
return pctrl->soc->ngroups;
}
static const char *chv_get_group_name(struct pinctrl_dev *pctldev,
unsigned int group)
{
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
return pctrl->soc->groups[group].grp.name;
}
static int chv_get_group_pins(struct pinctrl_dev *pctldev, unsigned int group,
const unsigned int **pins, unsigned int *npins)
{
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
*pins = pctrl->soc->groups[group].grp.pins;
*npins = pctrl->soc->groups[group].grp.npins;
return 0;
}
static void chv_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, static void chv_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
unsigned int offset) unsigned int offset)
{ {
@ -676,39 +651,12 @@ static void chv_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
} }
static const struct pinctrl_ops chv_pinctrl_ops = { static const struct pinctrl_ops chv_pinctrl_ops = {
.get_groups_count = chv_get_groups_count, .get_groups_count = intel_get_groups_count,
.get_group_name = chv_get_group_name, .get_group_name = intel_get_group_name,
.get_group_pins = chv_get_group_pins, .get_group_pins = intel_get_group_pins,
.pin_dbg_show = chv_pin_dbg_show, .pin_dbg_show = chv_pin_dbg_show,
}; };
static int chv_get_functions_count(struct pinctrl_dev *pctldev)
{
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
return pctrl->soc->nfunctions;
}
static const char *chv_get_function_name(struct pinctrl_dev *pctldev,
unsigned int function)
{
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
return pctrl->soc->functions[function].func.name;
}
static int chv_get_function_groups(struct pinctrl_dev *pctldev,
unsigned int function,
const char * const **groups,
unsigned int * const ngroups)
{
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
*groups = pctrl->soc->functions[function].func.groups;
*ngroups = pctrl->soc->functions[function].func.ngroups;
return 0;
}
static int chv_pinmux_set_mux(struct pinctrl_dev *pctldev, static int chv_pinmux_set_mux(struct pinctrl_dev *pctldev,
unsigned int function, unsigned int group) unsigned int function, unsigned int group)
{ {
@ -884,9 +832,9 @@ static int chv_gpio_set_direction(struct pinctrl_dev *pctldev,
} }
static const struct pinmux_ops chv_pinmux_ops = { static const struct pinmux_ops chv_pinmux_ops = {
.get_functions_count = chv_get_functions_count, .get_functions_count = intel_get_functions_count,
.get_function_name = chv_get_function_name, .get_function_name = intel_get_function_name,
.get_function_groups = chv_get_function_groups, .get_function_groups = intel_get_function_groups,
.set_mux = chv_pinmux_set_mux, .set_mux = chv_pinmux_set_mux,
.gpio_request_enable = chv_gpio_request_enable, .gpio_request_enable = chv_gpio_request_enable,
.gpio_disable_free = chv_gpio_disable_free, .gpio_disable_free = chv_gpio_disable_free,
@ -1118,7 +1066,7 @@ static int chv_config_group_get(struct pinctrl_dev *pctldev,
unsigned int npins; unsigned int npins;
int ret; int ret;
ret = chv_get_group_pins(pctldev, group, &pins, &npins); ret = intel_get_group_pins(pctldev, group, &pins, &npins);
if (ret) if (ret)
return ret; return ret;
@ -1137,7 +1085,7 @@ static int chv_config_group_set(struct pinctrl_dev *pctldev,
unsigned int npins; unsigned int npins;
int i, ret; int i, ret;
ret = chv_get_group_pins(pctldev, group, &pins, &npins); ret = intel_get_group_pins(pctldev, group, &pins, &npins);
if (ret) if (ret)
return ret; return ret;
@ -1701,7 +1649,6 @@ static int chv_pinctrl_probe(struct platform_device *pdev)
struct intel_community_context *cctx; struct intel_community_context *cctx;
struct intel_community *community; struct intel_community *community;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct acpi_device *adev = ACPI_COMPANION(dev);
struct intel_pinctrl *pctrl; struct intel_pinctrl *pctrl;
acpi_status status; acpi_status status;
unsigned int i; unsigned int i;
@ -1769,7 +1716,7 @@ static int chv_pinctrl_probe(struct platform_device *pdev)
if (ret) if (ret)
return ret; return ret;
status = acpi_install_address_space_handler(adev->handle, status = acpi_install_address_space_handler(ACPI_HANDLE(dev),
community->acpi_space_id, community->acpi_space_id,
chv_pinctrl_mmio_access_handler, chv_pinctrl_mmio_access_handler,
NULL, pctrl); NULL, pctrl);
@ -1786,14 +1733,13 @@ static int chv_pinctrl_remove(struct platform_device *pdev)
struct intel_pinctrl *pctrl = platform_get_drvdata(pdev); struct intel_pinctrl *pctrl = platform_get_drvdata(pdev);
const struct intel_community *community = &pctrl->communities[0]; const struct intel_community *community = &pctrl->communities[0];
acpi_remove_address_space_handler(ACPI_COMPANION(&pdev->dev), acpi_remove_address_space_handler(ACPI_HANDLE(&pdev->dev),
community->acpi_space_id, community->acpi_space_id,
chv_pinctrl_mmio_access_handler); chv_pinctrl_mmio_access_handler);
return 0; return 0;
} }
#ifdef CONFIG_PM_SLEEP
static int chv_pinctrl_suspend_noirq(struct device *dev) static int chv_pinctrl_suspend_noirq(struct device *dev)
{ {
struct intel_pinctrl *pctrl = dev_get_drvdata(dev); struct intel_pinctrl *pctrl = dev_get_drvdata(dev);
@ -1877,12 +1823,9 @@ static int chv_pinctrl_resume_noirq(struct device *dev)
return 0; return 0;
} }
#endif
static const struct dev_pm_ops chv_pinctrl_pm_ops = { static DEFINE_NOIRQ_DEV_PM_OPS(chv_pinctrl_pm_ops,
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(chv_pinctrl_suspend_noirq, chv_pinctrl_suspend_noirq, chv_pinctrl_resume_noirq);
chv_pinctrl_resume_noirq)
};
static const struct acpi_device_id chv_pinctrl_acpi_match[] = { static const struct acpi_device_id chv_pinctrl_acpi_match[] = {
{ "INT33FF", (kernel_ulong_t)chv_soc_data }, { "INT33FF", (kernel_ulong_t)chv_soc_data },
@ -1895,7 +1838,7 @@ static struct platform_driver chv_pinctrl_driver = {
.remove = chv_pinctrl_remove, .remove = chv_pinctrl_remove,
.driver = { .driver = {
.name = "cherryview-pinctrl", .name = "cherryview-pinctrl",
.pm = &chv_pinctrl_pm_ops, .pm = pm_sleep_ptr(&chv_pinctrl_pm_ops),
.acpi_match_table = chv_pinctrl_acpi_match, .acpi_match_table = chv_pinctrl_acpi_match,
}, },
}; };
@ -1915,3 +1858,4 @@ module_exit(chv_pinctrl_exit);
MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>"); MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
MODULE_DESCRIPTION("Intel Cherryview/Braswell pinctrl driver"); MODULE_DESCRIPTION("Intel Cherryview/Braswell pinctrl driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_IMPORT_NS(PINCTRL_INTEL);

View File

@ -281,3 +281,4 @@ module_exit(dnv_pinctrl_exit);
MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>"); MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
MODULE_DESCRIPTION("Intel Denverton SoC pinctrl/GPIO driver"); MODULE_DESCRIPTION("Intel Denverton SoC pinctrl/GPIO driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_IMPORT_NS(PINCTRL_INTEL);

View File

@ -495,9 +495,9 @@ static struct platform_driver ehl_pinctrl_driver = {
.pm = &ehl_pinctrl_pm_ops, .pm = &ehl_pinctrl_pm_ops,
}, },
}; };
module_platform_driver(ehl_pinctrl_driver); module_platform_driver(ehl_pinctrl_driver);
MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>"); MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
MODULE_DESCRIPTION("Intel Elkhart Lake PCH pinctrl/GPIO driver"); MODULE_DESCRIPTION("Intel Elkhart Lake PCH pinctrl/GPIO driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_IMPORT_NS(PINCTRL_INTEL);

View File

@ -368,9 +368,9 @@ static struct platform_driver ebg_pinctrl_driver = {
.pm = &ebg_pinctrl_pm_ops, .pm = &ebg_pinctrl_pm_ops,
}, },
}; };
module_platform_driver(ebg_pinctrl_driver); module_platform_driver(ebg_pinctrl_driver);
MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>"); MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
MODULE_DESCRIPTION("Intel Emmitsburg PCH pinctrl/GPIO driver"); MODULE_DESCRIPTION("Intel Emmitsburg PCH pinctrl/GPIO driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_IMPORT_NS(PINCTRL_INTEL);

View File

@ -473,3 +473,4 @@ module_exit(glk_pinctrl_exit);
MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>"); MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
MODULE_DESCRIPTION("Intel Gemini Lake SoC pinctrl/GPIO driver"); MODULE_DESCRIPTION("Intel Gemini Lake SoC pinctrl/GPIO driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_IMPORT_NS(PINCTRL_INTEL);

View File

@ -685,10 +685,10 @@ static struct platform_driver icl_pinctrl_driver = {
.pm = &icl_pinctrl_pm_ops, .pm = &icl_pinctrl_pm_ops,
}, },
}; };
module_platform_driver(icl_pinctrl_driver); module_platform_driver(icl_pinctrl_driver);
MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>"); MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>"); MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
MODULE_DESCRIPTION("Intel Ice Lake PCH pinctrl/GPIO driver"); MODULE_DESCRIPTION("Intel Ice Lake PCH pinctrl/GPIO driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_IMPORT_NS(PINCTRL_INTEL);

View File

@ -107,8 +107,7 @@ struct intel_community_context {
#define pin_to_padno(c, p) ((p) - (c)->pin_base) #define pin_to_padno(c, p) ((p) - (c)->pin_base)
#define padgroup_offset(g, p) ((p) - (g)->base) #define padgroup_offset(g, p) ((p) - (g)->base)
static struct intel_community *intel_get_community(struct intel_pinctrl *pctrl, struct intel_community *intel_get_community(struct intel_pinctrl *pctrl, unsigned int pin)
unsigned int pin)
{ {
struct intel_community *community; struct intel_community *community;
int i; int i;
@ -123,6 +122,7 @@ static struct intel_community *intel_get_community(struct intel_pinctrl *pctrl,
dev_warn(pctrl->dev, "failed to find community for pin %u\n", pin); dev_warn(pctrl->dev, "failed to find community for pin %u\n", pin);
return NULL; return NULL;
} }
EXPORT_SYMBOL_NS_GPL(intel_get_community, PINCTRL_INTEL);
static const struct intel_padgroup * static const struct intel_padgroup *
intel_community_get_padgroup(const struct intel_community *community, intel_community_get_padgroup(const struct intel_community *community,
@ -276,23 +276,24 @@ static bool intel_pad_usable(struct intel_pinctrl *pctrl, unsigned int pin)
return intel_pad_owned_by_host(pctrl, pin) && intel_pad_is_unlocked(pctrl, pin); return intel_pad_owned_by_host(pctrl, pin) && intel_pad_is_unlocked(pctrl, pin);
} }
static int intel_get_groups_count(struct pinctrl_dev *pctldev) int intel_get_groups_count(struct pinctrl_dev *pctldev)
{ {
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
return pctrl->soc->ngroups; return pctrl->soc->ngroups;
} }
EXPORT_SYMBOL_NS_GPL(intel_get_groups_count, PINCTRL_INTEL);
static const char *intel_get_group_name(struct pinctrl_dev *pctldev, const char *intel_get_group_name(struct pinctrl_dev *pctldev, unsigned int group)
unsigned int group)
{ {
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
return pctrl->soc->groups[group].grp.name; return pctrl->soc->groups[group].grp.name;
} }
EXPORT_SYMBOL_NS_GPL(intel_get_group_name, PINCTRL_INTEL);
static int intel_get_group_pins(struct pinctrl_dev *pctldev, unsigned int group, int intel_get_group_pins(struct pinctrl_dev *pctldev, unsigned int group,
const unsigned int **pins, unsigned int *npins) const unsigned int **pins, unsigned int *npins)
{ {
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
@ -300,6 +301,7 @@ static int intel_get_group_pins(struct pinctrl_dev *pctldev, unsigned int group,
*npins = pctrl->soc->groups[group].grp.npins; *npins = pctrl->soc->groups[group].grp.npins;
return 0; return 0;
} }
EXPORT_SYMBOL_NS_GPL(intel_get_group_pins, PINCTRL_INTEL);
static void intel_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, static void intel_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
unsigned int pin) unsigned int pin)
@ -359,25 +361,24 @@ static const struct pinctrl_ops intel_pinctrl_ops = {
.pin_dbg_show = intel_pin_dbg_show, .pin_dbg_show = intel_pin_dbg_show,
}; };
static int intel_get_functions_count(struct pinctrl_dev *pctldev) int intel_get_functions_count(struct pinctrl_dev *pctldev)
{ {
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
return pctrl->soc->nfunctions; return pctrl->soc->nfunctions;
} }
EXPORT_SYMBOL_NS_GPL(intel_get_functions_count, PINCTRL_INTEL);
static const char *intel_get_function_name(struct pinctrl_dev *pctldev, const char *intel_get_function_name(struct pinctrl_dev *pctldev, unsigned int function)
unsigned int function)
{ {
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
return pctrl->soc->functions[function].func.name; return pctrl->soc->functions[function].func.name;
} }
EXPORT_SYMBOL_NS_GPL(intel_get_function_name, PINCTRL_INTEL);
static int intel_get_function_groups(struct pinctrl_dev *pctldev, int intel_get_function_groups(struct pinctrl_dev *pctldev, unsigned int function,
unsigned int function, const char * const **groups, unsigned int * const ngroups)
const char * const **groups,
unsigned int * const ngroups)
{ {
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
@ -385,6 +386,7 @@ static int intel_get_function_groups(struct pinctrl_dev *pctldev,
*ngroups = pctrl->soc->functions[function].func.ngroups; *ngroups = pctrl->soc->functions[function].func.ngroups;
return 0; return 0;
} }
EXPORT_SYMBOL_NS_GPL(intel_get_function_groups, PINCTRL_INTEL);
static int intel_pinmux_set_mux(struct pinctrl_dev *pctldev, static int intel_pinmux_set_mux(struct pinctrl_dev *pctldev,
unsigned int function, unsigned int group) unsigned int function, unsigned int group)
@ -1666,7 +1668,7 @@ int intel_pinctrl_probe_by_hid(struct platform_device *pdev)
return intel_pinctrl_probe(pdev, data); return intel_pinctrl_probe(pdev, data);
} }
EXPORT_SYMBOL_GPL(intel_pinctrl_probe_by_hid); EXPORT_SYMBOL_NS_GPL(intel_pinctrl_probe_by_hid, PINCTRL_INTEL);
int intel_pinctrl_probe_by_uid(struct platform_device *pdev) int intel_pinctrl_probe_by_uid(struct platform_device *pdev)
{ {
@ -1678,7 +1680,7 @@ int intel_pinctrl_probe_by_uid(struct platform_device *pdev)
return intel_pinctrl_probe(pdev, data); return intel_pinctrl_probe(pdev, data);
} }
EXPORT_SYMBOL_GPL(intel_pinctrl_probe_by_uid); EXPORT_SYMBOL_NS_GPL(intel_pinctrl_probe_by_uid, PINCTRL_INTEL);
const struct intel_pinctrl_soc_data *intel_pinctrl_get_soc_data(struct platform_device *pdev) const struct intel_pinctrl_soc_data *intel_pinctrl_get_soc_data(struct platform_device *pdev)
{ {
@ -1710,7 +1712,7 @@ const struct intel_pinctrl_soc_data *intel_pinctrl_get_soc_data(struct platform_
return data ?: ERR_PTR(-ENODATA); return data ?: ERR_PTR(-ENODATA);
} }
EXPORT_SYMBOL_GPL(intel_pinctrl_get_soc_data); EXPORT_SYMBOL_NS_GPL(intel_pinctrl_get_soc_data, PINCTRL_INTEL);
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static bool __intel_gpio_is_direct_irq(u32 value) static bool __intel_gpio_is_direct_irq(u32 value)

View File

@ -266,4 +266,16 @@ const struct dev_pm_ops _name = { \
intel_pinctrl_resume_noirq) \ intel_pinctrl_resume_noirq) \
} }
struct intel_community *intel_get_community(struct intel_pinctrl *pctrl, unsigned int pin);
int intel_get_groups_count(struct pinctrl_dev *pctldev);
const char *intel_get_group_name(struct pinctrl_dev *pctldev, unsigned int group);
int intel_get_group_pins(struct pinctrl_dev *pctldev, unsigned int group,
const unsigned int **pins, unsigned int *npins);
int intel_get_functions_count(struct pinctrl_dev *pctldev);
const char *intel_get_function_name(struct pinctrl_dev *pctldev, unsigned int function);
int intel_get_function_groups(struct pinctrl_dev *pctldev, unsigned int function,
const char * const **groups, unsigned int * const ngroups);
#endif /* PINCTRL_INTEL_H */ #endif /* PINCTRL_INTEL_H */

View File

@ -341,3 +341,4 @@ module_platform_driver(jsl_pinctrl_driver);
MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>"); MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
MODULE_DESCRIPTION("Intel Jasper Lake PCH pinctrl/GPIO driver"); MODULE_DESCRIPTION("Intel Jasper Lake PCH pinctrl/GPIO driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_IMPORT_NS(PINCTRL_INTEL);

View File

@ -362,3 +362,4 @@ module_platform_driver(lkf_pinctrl_driver);
MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>"); MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
MODULE_DESCRIPTION("Intel Lakefield PCH pinctrl/GPIO driver"); MODULE_DESCRIPTION("Intel Lakefield PCH pinctrl/GPIO driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_IMPORT_NS(PINCTRL_INTEL);

View File

@ -317,9 +317,9 @@ static struct platform_driver lbg_pinctrl_driver = {
.pm = &lbg_pinctrl_pm_ops, .pm = &lbg_pinctrl_pm_ops,
}, },
}; };
module_platform_driver(lbg_pinctrl_driver); module_platform_driver(lbg_pinctrl_driver);
MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>"); MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
MODULE_DESCRIPTION("Intel Lewisburg pinctrl/GPIO driver"); MODULE_DESCRIPTION("Intel Lewisburg pinctrl/GPIO driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_IMPORT_NS(PINCTRL_INTEL);

View File

@ -206,21 +206,6 @@ static const struct intel_pinctrl_soc_data lptlp_soc_data = {
* IOxAPIC redirection map applies only for gpio 8-10, 13-14, 45-55. * 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, static void __iomem *lp_gpio_reg(struct gpio_chip *chip, unsigned int offset,
int reg) int reg)
{ {
@ -228,7 +213,7 @@ static void __iomem *lp_gpio_reg(struct gpio_chip *chip, unsigned int offset,
struct intel_community *comm; struct intel_community *comm;
int reg_offset; int reg_offset;
comm = lp_get_community(lg, offset); comm = intel_get_community(lg, offset);
if (!comm) if (!comm)
return NULL; return NULL;
@ -272,34 +257,6 @@ static bool lp_gpio_ioxapic_use(struct gpio_chip *chip, unsigned int offset)
return false; 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].grp.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].grp.pins;
*num_pins = lg->soc->groups[selector].grp.npins;
return 0;
}
static void lp_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, static void lp_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
unsigned int pin) unsigned int pin)
{ {
@ -323,40 +280,12 @@ static void lp_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
} }
static const struct pinctrl_ops lptlp_pinctrl_ops = { static const struct pinctrl_ops lptlp_pinctrl_ops = {
.get_groups_count = lp_get_groups_count, .get_groups_count = intel_get_groups_count,
.get_group_name = lp_get_group_name, .get_group_name = intel_get_group_name,
.get_group_pins = lp_get_group_pins, .get_group_pins = intel_get_group_pins,
.pin_dbg_show = lp_pin_dbg_show, .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].func.name;
}
static int lp_get_function_groups(struct pinctrl_dev *pctldev,
unsigned int selector,
const char * const **groups,
unsigned int *ngroups)
{
struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev);
*groups = lg->soc->functions[selector].func.groups;
*ngroups = lg->soc->functions[selector].func.ngroups;
return 0;
}
static int lp_pinmux_set_mux(struct pinctrl_dev *pctldev, static int lp_pinmux_set_mux(struct pinctrl_dev *pctldev,
unsigned int function, unsigned int group) unsigned int function, unsigned int group)
{ {
@ -481,9 +410,9 @@ static int lp_gpio_set_direction(struct pinctrl_dev *pctldev,
} }
static const struct pinmux_ops lptlp_pinmux_ops = { static const struct pinmux_ops lptlp_pinmux_ops = {
.get_functions_count = lp_get_functions_count, .get_functions_count = intel_get_functions_count,
.get_function_name = lp_get_function_name, .get_function_name = intel_get_function_name,
.get_function_groups = lp_get_function_groups, .get_function_groups = intel_get_function_groups,
.set_mux = lp_pinmux_set_mux, .set_mux = lp_pinmux_set_mux,
.gpio_request_enable = lp_gpio_request_enable, .gpio_request_enable = lp_gpio_request_enable,
.gpio_disable_free = lp_gpio_disable_free, .gpio_disable_free = lp_gpio_disable_free,
@ -948,9 +877,8 @@ static int lp_gpio_resume(struct device *dev)
} }
static const struct dev_pm_ops lp_gpio_pm_ops = { static const struct dev_pm_ops lp_gpio_pm_ops = {
.runtime_suspend = lp_gpio_runtime_suspend, SYSTEM_SLEEP_PM_OPS(NULL, lp_gpio_resume)
.runtime_resume = lp_gpio_runtime_resume, RUNTIME_PM_OPS(lp_gpio_runtime_suspend, lp_gpio_runtime_resume, NULL)
.resume = lp_gpio_resume,
}; };
static const struct acpi_device_id lynxpoint_gpio_acpi_match[] = { static const struct acpi_device_id lynxpoint_gpio_acpi_match[] = {
@ -965,7 +893,7 @@ static struct platform_driver lp_gpio_driver = {
.remove = lp_gpio_remove, .remove = lp_gpio_remove,
.driver = { .driver = {
.name = "lp_gpio", .name = "lp_gpio",
.pm = &lp_gpio_pm_ops, .pm = pm_ptr(&lp_gpio_pm_ops),
.acpi_match_table = lynxpoint_gpio_acpi_match, .acpi_match_table = lynxpoint_gpio_acpi_match,
}, },
}; };
@ -987,3 +915,4 @@ MODULE_AUTHOR("Andy Shevchenko (Intel)");
MODULE_DESCRIPTION("Intel Lynxpoint pinctrl driver"); MODULE_DESCRIPTION("Intel Lynxpoint pinctrl driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:lp_gpio"); MODULE_ALIAS("platform:lp_gpio");
MODULE_IMPORT_NS(PINCTRL_INTEL);

View File

@ -6,85 +6,17 @@
* Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com> * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
*/ */
#include <linux/bits.h> #include <linux/init.h>
#include <linux/err.h> #include <linux/kernel.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h> #include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/seq_file.h> #include <linux/types.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include "pinctrl-intel.h" #include "pinctrl-intel.h"
#include "pinctrl-tangier.h"
#define MRFLD_FAMILY_NR 64
#define MRFLD_FAMILY_LEN 0x400
#define SLEW_OFFSET 0x000
#define BUFCFG_OFFSET 0x100
#define MISC_OFFSET 0x300
#define BUFCFG_PINMODE_SHIFT 0
#define BUFCFG_PINMODE_MASK GENMASK(2, 0)
#define BUFCFG_PINMODE_GPIO 0
#define BUFCFG_PUPD_VAL_SHIFT 4
#define BUFCFG_PUPD_VAL_MASK GENMASK(5, 4)
#define BUFCFG_PUPD_VAL_2K 0
#define BUFCFG_PUPD_VAL_20K 1
#define BUFCFG_PUPD_VAL_50K 2
#define BUFCFG_PUPD_VAL_910 3
#define BUFCFG_PU_EN BIT(8)
#define BUFCFG_PD_EN BIT(9)
#define BUFCFG_Px_EN_MASK GENMASK(9, 8)
#define BUFCFG_SLEWSEL BIT(10)
#define BUFCFG_OVINEN BIT(12)
#define BUFCFG_OVINEN_EN BIT(13)
#define BUFCFG_OVINEN_MASK GENMASK(13, 12)
#define BUFCFG_OVOUTEN BIT(14)
#define BUFCFG_OVOUTEN_EN BIT(15)
#define BUFCFG_OVOUTEN_MASK GENMASK(15, 14)
#define BUFCFG_INDATAOV_VAL BIT(16)
#define BUFCFG_INDATAOV_EN BIT(17)
#define BUFCFG_INDATAOV_MASK GENMASK(17, 16)
#define BUFCFG_OUTDATAOV_VAL BIT(18)
#define BUFCFG_OUTDATAOV_EN BIT(19)
#define BUFCFG_OUTDATAOV_MASK GENMASK(19, 18)
#define BUFCFG_OD_EN BIT(21)
/**
* struct mrfld_family - Intel pin family description
* @barno: MMIO BAR number where registers for this family reside
* @pin_base: Starting pin of pins in this family
* @npins: Number of pins in this family
* @protected: True if family is protected by access
* @regs: family specific common registers
*/
struct mrfld_family {
unsigned int barno;
unsigned int pin_base;
size_t npins;
bool protected;
void __iomem *regs;
};
#define MRFLD_FAMILY(b, s, e) \
{ \
.barno = (b), \
.pin_base = (s), \
.npins = (e) - (s) + 1, \
}
#define MRFLD_FAMILY_PROTECTED(b, s, e) \
{ \
.barno = (b), \
.pin_base = (s), \
.npins = (e) - (s) + 1, \
.protected = true, \
}
static const struct pinctrl_pin_desc mrfld_pins[] = { static const struct pinctrl_pin_desc mrfld_pins[] = {
/* Family 0: OCP2SSC (0 pins) */ /* Family 0: OCP2SSC (0 pins) */
@ -389,587 +321,43 @@ static const struct intel_function mrfld_functions[] = {
FUNCTION("pwm3", mrfld_pwm3_groups), FUNCTION("pwm3", mrfld_pwm3_groups),
}; };
static const struct mrfld_family mrfld_families[] = { static const struct tng_family mrfld_families[] = {
MRFLD_FAMILY(1, 0, 12), TNG_FAMILY(1, 0, 12),
MRFLD_FAMILY(2, 13, 36), TNG_FAMILY(2, 13, 36),
MRFLD_FAMILY(3, 37, 56), TNG_FAMILY(3, 37, 56),
MRFLD_FAMILY(4, 57, 64), TNG_FAMILY(4, 57, 64),
MRFLD_FAMILY(5, 65, 78), TNG_FAMILY(5, 65, 78),
MRFLD_FAMILY(6, 79, 100), TNG_FAMILY(6, 79, 100),
MRFLD_FAMILY_PROTECTED(7, 101, 114), TNG_FAMILY_PROTECTED(7, 101, 114),
MRFLD_FAMILY(8, 115, 126), TNG_FAMILY(8, 115, 126),
MRFLD_FAMILY(9, 127, 145), TNG_FAMILY(9, 127, 145),
MRFLD_FAMILY(10, 146, 157), TNG_FAMILY(10, 146, 157),
MRFLD_FAMILY(11, 158, 179), TNG_FAMILY(11, 158, 179),
MRFLD_FAMILY_PROTECTED(12, 180, 194), TNG_FAMILY_PROTECTED(12, 180, 194),
MRFLD_FAMILY(13, 195, 214), TNG_FAMILY(13, 195, 214),
MRFLD_FAMILY(14, 215, 227), TNG_FAMILY(14, 215, 227),
MRFLD_FAMILY(15, 228, 232), TNG_FAMILY(15, 228, 232),
}; };
/** static const struct tng_pinctrl mrfld_soc_data = {
* struct mrfld_pinctrl - Intel Merrifield pinctrl private structure .pins = mrfld_pins,
* @dev: Pointer to the device structure .npins = ARRAY_SIZE(mrfld_pins),
* @lock: Lock to serialize register access .groups = mrfld_groups,
* @pctldesc: Pin controller description .ngroups = ARRAY_SIZE(mrfld_groups),
* @pctldev: Pointer to the pin controller device .families = mrfld_families,
* @families: Array of families this pinctrl handles .nfamilies = ARRAY_SIZE(mrfld_families),
* @nfamilies: Number of families in the array .functions = mrfld_functions,
* @functions: Array of functions .nfunctions = ARRAY_SIZE(mrfld_functions),
* @nfunctions: Number of functions in the array
* @groups: Array of pin groups
* @ngroups: Number of groups in the array
* @pins: Array of pins this pinctrl controls
* @npins: Number of pins in the array
*/
struct mrfld_pinctrl {
struct device *dev;
raw_spinlock_t lock;
struct pinctrl_desc pctldesc;
struct pinctrl_dev *pctldev;
/* Pin controller configuration */
const struct mrfld_family *families;
size_t nfamilies;
const struct intel_function *functions;
size_t nfunctions;
const struct intel_pingroup *groups;
size_t ngroups;
const struct pinctrl_pin_desc *pins;
size_t npins;
}; };
#define pin_to_bufno(f, p) ((p) - (f)->pin_base)
static const struct mrfld_family *mrfld_get_family(struct mrfld_pinctrl *mp,
unsigned int pin)
{
const struct mrfld_family *family;
unsigned int i;
for (i = 0; i < mp->nfamilies; i++) {
family = &mp->families[i];
if (pin >= family->pin_base &&
pin < family->pin_base + family->npins)
return family;
}
dev_warn(mp->dev, "failed to find family for pin %u\n", pin);
return NULL;
}
static bool mrfld_buf_available(struct mrfld_pinctrl *mp, unsigned int pin)
{
const struct mrfld_family *family;
family = mrfld_get_family(mp, pin);
if (!family)
return false;
return !family->protected;
}
static void __iomem *mrfld_get_bufcfg(struct mrfld_pinctrl *mp, unsigned int pin)
{
const struct mrfld_family *family;
unsigned int bufno;
family = mrfld_get_family(mp, pin);
if (!family)
return NULL;
bufno = pin_to_bufno(family, pin);
return family->regs + BUFCFG_OFFSET + bufno * 4;
}
static int mrfld_read_bufcfg(struct mrfld_pinctrl *mp, unsigned int pin, u32 *value)
{
void __iomem *bufcfg;
if (!mrfld_buf_available(mp, pin))
return -EBUSY;
bufcfg = mrfld_get_bufcfg(mp, pin);
*value = readl(bufcfg);
return 0;
}
static void mrfld_update_bufcfg(struct mrfld_pinctrl *mp, unsigned int pin,
u32 bits, u32 mask)
{
void __iomem *bufcfg;
u32 value;
bufcfg = mrfld_get_bufcfg(mp, pin);
value = readl(bufcfg);
value &= ~mask;
value |= bits & mask;
writel(value, bufcfg);
}
static int mrfld_get_groups_count(struct pinctrl_dev *pctldev)
{
struct mrfld_pinctrl *mp = pinctrl_dev_get_drvdata(pctldev);
return mp->ngroups;
}
static const char *mrfld_get_group_name(struct pinctrl_dev *pctldev,
unsigned int group)
{
struct mrfld_pinctrl *mp = pinctrl_dev_get_drvdata(pctldev);
return mp->groups[group].grp.name;
}
static int mrfld_get_group_pins(struct pinctrl_dev *pctldev, unsigned int group,
const unsigned int **pins, unsigned int *npins)
{
struct mrfld_pinctrl *mp = pinctrl_dev_get_drvdata(pctldev);
*pins = mp->groups[group].grp.pins;
*npins = mp->groups[group].grp.npins;
return 0;
}
static void mrfld_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
unsigned int pin)
{
struct mrfld_pinctrl *mp = pinctrl_dev_get_drvdata(pctldev);
u32 value, mode;
int ret;
ret = mrfld_read_bufcfg(mp, pin, &value);
if (ret) {
seq_puts(s, "not available");
return;
}
mode = (value & BUFCFG_PINMODE_MASK) >> BUFCFG_PINMODE_SHIFT;
if (mode == BUFCFG_PINMODE_GPIO)
seq_puts(s, "GPIO ");
else
seq_printf(s, "mode %d ", mode);
seq_printf(s, "0x%08x", value);
}
static const struct pinctrl_ops mrfld_pinctrl_ops = {
.get_groups_count = mrfld_get_groups_count,
.get_group_name = mrfld_get_group_name,
.get_group_pins = mrfld_get_group_pins,
.pin_dbg_show = mrfld_pin_dbg_show,
};
static int mrfld_get_functions_count(struct pinctrl_dev *pctldev)
{
struct mrfld_pinctrl *mp = pinctrl_dev_get_drvdata(pctldev);
return mp->nfunctions;
}
static const char *mrfld_get_function_name(struct pinctrl_dev *pctldev,
unsigned int function)
{
struct mrfld_pinctrl *mp = pinctrl_dev_get_drvdata(pctldev);
return mp->functions[function].func.name;
}
static int mrfld_get_function_groups(struct pinctrl_dev *pctldev,
unsigned int function,
const char * const **groups,
unsigned int * const ngroups)
{
struct mrfld_pinctrl *mp = pinctrl_dev_get_drvdata(pctldev);
*groups = mp->functions[function].func.groups;
*ngroups = mp->functions[function].func.ngroups;
return 0;
}
static int mrfld_pinmux_set_mux(struct pinctrl_dev *pctldev,
unsigned int function,
unsigned int group)
{
struct mrfld_pinctrl *mp = pinctrl_dev_get_drvdata(pctldev);
const struct intel_pingroup *grp = &mp->groups[group];
u32 bits = grp->mode << BUFCFG_PINMODE_SHIFT;
u32 mask = BUFCFG_PINMODE_MASK;
unsigned long flags;
unsigned int i;
/*
* All pins in the groups needs to be accessible and writable
* before we can enable the mux for this group.
*/
for (i = 0; i < grp->grp.npins; i++) {
if (!mrfld_buf_available(mp, grp->grp.pins[i]))
return -EBUSY;
}
/* Now enable the mux setting for each pin in the group */
raw_spin_lock_irqsave(&mp->lock, flags);
for (i = 0; i < grp->grp.npins; i++)
mrfld_update_bufcfg(mp, grp->grp.pins[i], bits, mask);
raw_spin_unlock_irqrestore(&mp->lock, flags);
return 0;
}
static int mrfld_gpio_request_enable(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned int pin)
{
struct mrfld_pinctrl *mp = pinctrl_dev_get_drvdata(pctldev);
u32 bits = BUFCFG_PINMODE_GPIO << BUFCFG_PINMODE_SHIFT;
u32 mask = BUFCFG_PINMODE_MASK;
unsigned long flags;
if (!mrfld_buf_available(mp, pin))
return -EBUSY;
raw_spin_lock_irqsave(&mp->lock, flags);
mrfld_update_bufcfg(mp, pin, bits, mask);
raw_spin_unlock_irqrestore(&mp->lock, flags);
return 0;
}
static const struct pinmux_ops mrfld_pinmux_ops = {
.get_functions_count = mrfld_get_functions_count,
.get_function_name = mrfld_get_function_name,
.get_function_groups = mrfld_get_function_groups,
.set_mux = mrfld_pinmux_set_mux,
.gpio_request_enable = mrfld_gpio_request_enable,
};
static int mrfld_config_get(struct pinctrl_dev *pctldev, unsigned int pin,
unsigned long *config)
{
struct mrfld_pinctrl *mp = pinctrl_dev_get_drvdata(pctldev);
enum pin_config_param param = pinconf_to_config_param(*config);
u32 value, term;
u16 arg = 0;
int ret;
ret = mrfld_read_bufcfg(mp, pin, &value);
if (ret)
return -ENOTSUPP;
term = (value & BUFCFG_PUPD_VAL_MASK) >> BUFCFG_PUPD_VAL_SHIFT;
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
if (value & BUFCFG_Px_EN_MASK)
return -EINVAL;
break;
case PIN_CONFIG_BIAS_PULL_UP:
if ((value & BUFCFG_Px_EN_MASK) != BUFCFG_PU_EN)
return -EINVAL;
switch (term) {
case BUFCFG_PUPD_VAL_910:
arg = 910;
break;
case BUFCFG_PUPD_VAL_2K:
arg = 2000;
break;
case BUFCFG_PUPD_VAL_20K:
arg = 20000;
break;
case BUFCFG_PUPD_VAL_50K:
arg = 50000;
break;
}
break;
case PIN_CONFIG_BIAS_PULL_DOWN:
if ((value & BUFCFG_Px_EN_MASK) != BUFCFG_PD_EN)
return -EINVAL;
switch (term) {
case BUFCFG_PUPD_VAL_910:
arg = 910;
break;
case BUFCFG_PUPD_VAL_2K:
arg = 2000;
break;
case BUFCFG_PUPD_VAL_20K:
arg = 20000;
break;
case BUFCFG_PUPD_VAL_50K:
arg = 50000;
break;
}
break;
case PIN_CONFIG_DRIVE_PUSH_PULL:
if (value & BUFCFG_OD_EN)
return -EINVAL;
break;
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
if (!(value & BUFCFG_OD_EN))
return -EINVAL;
break;
case PIN_CONFIG_SLEW_RATE:
if (!(value & BUFCFG_SLEWSEL))
arg = 0;
else
arg = 1;
break;
default:
return -ENOTSUPP;
}
*config = pinconf_to_config_packed(param, arg);
return 0;
}
static int mrfld_config_set_pin(struct mrfld_pinctrl *mp, unsigned int pin,
unsigned long config)
{
unsigned int param = pinconf_to_config_param(config);
unsigned int arg = pinconf_to_config_argument(config);
u32 bits = 0, mask = 0;
unsigned long flags;
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
mask |= BUFCFG_Px_EN_MASK | BUFCFG_PUPD_VAL_MASK;
break;
case PIN_CONFIG_BIAS_PULL_UP:
mask |= BUFCFG_Px_EN_MASK | BUFCFG_PUPD_VAL_MASK;
bits |= BUFCFG_PU_EN;
/* Set default strength value in case none is given */
if (arg == 1)
arg = 20000;
switch (arg) {
case 50000:
bits |= BUFCFG_PUPD_VAL_50K << BUFCFG_PUPD_VAL_SHIFT;
break;
case 20000:
bits |= BUFCFG_PUPD_VAL_20K << BUFCFG_PUPD_VAL_SHIFT;
break;
case 2000:
bits |= BUFCFG_PUPD_VAL_2K << BUFCFG_PUPD_VAL_SHIFT;
break;
default:
return -EINVAL;
}
break;
case PIN_CONFIG_BIAS_PULL_DOWN:
mask |= BUFCFG_Px_EN_MASK | BUFCFG_PUPD_VAL_MASK;
bits |= BUFCFG_PD_EN;
/* Set default strength value in case none is given */
if (arg == 1)
arg = 20000;
switch (arg) {
case 50000:
bits |= BUFCFG_PUPD_VAL_50K << BUFCFG_PUPD_VAL_SHIFT;
break;
case 20000:
bits |= BUFCFG_PUPD_VAL_20K << BUFCFG_PUPD_VAL_SHIFT;
break;
case 2000:
bits |= BUFCFG_PUPD_VAL_2K << BUFCFG_PUPD_VAL_SHIFT;
break;
default:
return -EINVAL;
}
break;
case PIN_CONFIG_DRIVE_PUSH_PULL:
mask |= BUFCFG_OD_EN;
bits &= ~BUFCFG_OD_EN;
break;
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
mask |= BUFCFG_OD_EN;
bits |= BUFCFG_OD_EN;
break;
case PIN_CONFIG_SLEW_RATE:
mask |= BUFCFG_SLEWSEL;
if (arg)
bits |= BUFCFG_SLEWSEL;
break;
}
raw_spin_lock_irqsave(&mp->lock, flags);
mrfld_update_bufcfg(mp, pin, bits, mask);
raw_spin_unlock_irqrestore(&mp->lock, flags);
return 0;
}
static int mrfld_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
unsigned long *configs, unsigned int nconfigs)
{
struct mrfld_pinctrl *mp = pinctrl_dev_get_drvdata(pctldev);
unsigned int i;
int ret;
if (!mrfld_buf_available(mp, pin))
return -ENOTSUPP;
for (i = 0; i < nconfigs; i++) {
switch (pinconf_to_config_param(configs[i])) {
case PIN_CONFIG_BIAS_DISABLE:
case PIN_CONFIG_BIAS_PULL_UP:
case PIN_CONFIG_BIAS_PULL_DOWN:
case PIN_CONFIG_DRIVE_PUSH_PULL:
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
case PIN_CONFIG_SLEW_RATE:
ret = mrfld_config_set_pin(mp, pin, configs[i]);
if (ret)
return ret;
break;
default:
return -ENOTSUPP;
}
}
return 0;
}
static int mrfld_config_group_get(struct pinctrl_dev *pctldev,
unsigned int group, unsigned long *config)
{
const unsigned int *pins;
unsigned int npins;
int ret;
ret = mrfld_get_group_pins(pctldev, group, &pins, &npins);
if (ret)
return ret;
ret = mrfld_config_get(pctldev, pins[0], config);
if (ret)
return ret;
return 0;
}
static int mrfld_config_group_set(struct pinctrl_dev *pctldev,
unsigned int group, unsigned long *configs,
unsigned int num_configs)
{
const unsigned int *pins;
unsigned int npins;
int i, ret;
ret = mrfld_get_group_pins(pctldev, group, &pins, &npins);
if (ret)
return ret;
for (i = 0; i < npins; i++) {
ret = mrfld_config_set(pctldev, pins[i], configs, num_configs);
if (ret)
return ret;
}
return 0;
}
static const struct pinconf_ops mrfld_pinconf_ops = {
.is_generic = true,
.pin_config_get = mrfld_config_get,
.pin_config_set = mrfld_config_set,
.pin_config_group_get = mrfld_config_group_get,
.pin_config_group_set = mrfld_config_group_set,
};
static const struct pinctrl_desc mrfld_pinctrl_desc = {
.pctlops = &mrfld_pinctrl_ops,
.pmxops = &mrfld_pinmux_ops,
.confops = &mrfld_pinconf_ops,
.owner = THIS_MODULE,
};
static int mrfld_pinctrl_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct mrfld_family *families;
struct mrfld_pinctrl *mp;
void __iomem *regs;
size_t nfamilies;
unsigned int i;
mp = devm_kzalloc(dev, sizeof(*mp), GFP_KERNEL);
if (!mp)
return -ENOMEM;
mp->dev = dev;
raw_spin_lock_init(&mp->lock);
regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(regs))
return PTR_ERR(regs);
/*
* Make a copy of the families which we can use to hold pointers
* to the registers.
*/
nfamilies = ARRAY_SIZE(mrfld_families),
families = devm_kmemdup(dev, mrfld_families, sizeof(mrfld_families), GFP_KERNEL);
if (!families)
return -ENOMEM;
/* Splice memory resource by chunk per family */
for (i = 0; i < nfamilies; i++) {
struct mrfld_family *family = &families[i];
family->regs = regs + family->barno * MRFLD_FAMILY_LEN;
}
mp->families = families;
mp->nfamilies = nfamilies;
mp->functions = mrfld_functions;
mp->nfunctions = ARRAY_SIZE(mrfld_functions);
mp->groups = mrfld_groups;
mp->ngroups = ARRAY_SIZE(mrfld_groups);
mp->pctldesc = mrfld_pinctrl_desc;
mp->pctldesc.name = dev_name(dev);
mp->pctldesc.pins = mrfld_pins;
mp->pctldesc.npins = ARRAY_SIZE(mrfld_pins);
mp->pctldev = devm_pinctrl_register(dev, &mp->pctldesc, mp);
if (IS_ERR(mp->pctldev)) {
dev_err(dev, "failed to register pinctrl driver\n");
return PTR_ERR(mp->pctldev);
}
platform_set_drvdata(pdev, mp);
return 0;
}
static const struct acpi_device_id mrfld_acpi_table[] = { static const struct acpi_device_id mrfld_acpi_table[] = {
{ "INTC1002" }, { "INTC1002", (kernel_ulong_t)&mrfld_soc_data },
{ } { }
}; };
MODULE_DEVICE_TABLE(acpi, mrfld_acpi_table); MODULE_DEVICE_TABLE(acpi, mrfld_acpi_table);
static struct platform_driver mrfld_pinctrl_driver = { static struct platform_driver mrfld_pinctrl_driver = {
.probe = mrfld_pinctrl_probe, .probe = devm_tng_pinctrl_probe,
.driver = { .driver = {
.name = "pinctrl-merrifield", .name = "pinctrl-merrifield",
.acpi_match_table = mrfld_acpi_table, .acpi_match_table = mrfld_acpi_table,
@ -992,3 +380,4 @@ MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
MODULE_DESCRIPTION("Intel Merrifield SoC pinctrl driver"); MODULE_DESCRIPTION("Intel Merrifield SoC pinctrl driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:pinctrl-merrifield"); MODULE_ALIAS("platform:pinctrl-merrifield");
MODULE_IMPORT_NS(PINCTRL_TANGIER);

View File

@ -604,3 +604,4 @@ module_platform_driver(mtl_pinctrl_driver);
MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>"); MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
MODULE_DESCRIPTION("Intel Meteor Lake PCH pinctrl/GPIO driver"); MODULE_DESCRIPTION("Intel Meteor Lake PCH pinctrl/GPIO driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_IMPORT_NS(PINCTRL_INTEL);

View File

@ -6,77 +6,16 @@
* Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com> * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
*/ */
#include <linux/bits.h> #include <linux/init.h>
#include <linux/err.h> #include <linux/kernel.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h> #include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/seq_file.h> #include <linux/types.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include "pinctrl-intel.h" #include "pinctrl-tangier.h"
#define MOFLD_FAMILY_NR 64
#define MOFLD_FAMILY_LEN 0x400
#define SLEW_OFFSET 0x000
#define BUFCFG_OFFSET 0x100
#define MISC_OFFSET 0x300
#define BUFCFG_PINMODE_SHIFT 0
#define BUFCFG_PINMODE_MASK GENMASK(2, 0)
#define BUFCFG_PINMODE_GPIO 0
#define BUFCFG_PUPD_VAL_SHIFT 4
#define BUFCFG_PUPD_VAL_MASK GENMASK(5, 4)
#define BUFCFG_PUPD_VAL_2K 0
#define BUFCFG_PUPD_VAL_20K 1
#define BUFCFG_PUPD_VAL_50K 2
#define BUFCFG_PUPD_VAL_910 3
#define BUFCFG_PU_EN BIT(8)
#define BUFCFG_PD_EN BIT(9)
#define BUFCFG_Px_EN_MASK GENMASK(9, 8)
#define BUFCFG_SLEWSEL BIT(10)
#define BUFCFG_OVINEN BIT(12)
#define BUFCFG_OVINEN_EN BIT(13)
#define BUFCFG_OVINEN_MASK GENMASK(13, 12)
#define BUFCFG_OVOUTEN BIT(14)
#define BUFCFG_OVOUTEN_EN BIT(15)
#define BUFCFG_OVOUTEN_MASK GENMASK(15, 14)
#define BUFCFG_INDATAOV_VAL BIT(16)
#define BUFCFG_INDATAOV_EN BIT(17)
#define BUFCFG_INDATAOV_MASK GENMASK(17, 16)
#define BUFCFG_OUTDATAOV_VAL BIT(18)
#define BUFCFG_OUTDATAOV_EN BIT(19)
#define BUFCFG_OUTDATAOV_MASK GENMASK(19, 18)
#define BUFCFG_OD_EN BIT(21)
/**
* struct mofld_family - Intel pin family description
* @barno: MMIO BAR number where registers for this family reside
* @pin_base: Starting pin of pins in this family
* @npins: Number of pins in this family
* @protected: True if family is protected by access
* @regs: family specific common registers
*/
struct mofld_family {
unsigned int barno;
unsigned int pin_base;
size_t npins;
bool protected;
void __iomem *regs;
};
#define MOFLD_FAMILY(b, s, e) \
{ \
.barno = (b), \
.pin_base = (s), \
.npins = (e) - (s) + 1, \
}
static const struct pinctrl_pin_desc mofld_pins[] = { static const struct pinctrl_pin_desc mofld_pins[] = {
/* ULPI (13 pins) */ /* ULPI (13 pins) */
@ -347,561 +286,39 @@ static const struct pinctrl_pin_desc mofld_pins[] = {
PINCTRL_PIN(250, "JTAG_TRST"), PINCTRL_PIN(250, "JTAG_TRST"),
}; };
static const struct mofld_family mofld_families[] = { static const struct tng_family mofld_families[] = {
MOFLD_FAMILY(0, 0, 12), TNG_FAMILY(0, 0, 12),
MOFLD_FAMILY(1, 13, 24), TNG_FAMILY(1, 13, 24),
MOFLD_FAMILY(2, 25, 44), TNG_FAMILY(2, 25, 44),
MOFLD_FAMILY(3, 45, 52), TNG_FAMILY(3, 45, 52),
MOFLD_FAMILY(4, 53, 66), TNG_FAMILY(4, 53, 66),
MOFLD_FAMILY(5, 67, 88), TNG_FAMILY(5, 67, 88),
MOFLD_FAMILY(6, 89, 108), TNG_FAMILY(6, 89, 108),
MOFLD_FAMILY(7, 109, 131), TNG_FAMILY(7, 109, 131),
MOFLD_FAMILY(8, 132, 151), TNG_FAMILY(8, 132, 151),
MOFLD_FAMILY(9, 152, 166), TNG_FAMILY(9, 152, 166),
MOFLD_FAMILY(10, 167, 180), TNG_FAMILY(10, 167, 180),
MOFLD_FAMILY(11, 181, 195), TNG_FAMILY(11, 181, 195),
MOFLD_FAMILY(12, 196, 215), TNG_FAMILY(12, 196, 215),
MOFLD_FAMILY(13, 216, 228), TNG_FAMILY(13, 216, 228),
MOFLD_FAMILY(14, 229, 250), TNG_FAMILY(14, 229, 250),
}; };
/** static const struct tng_pinctrl mofld_soc_data = {
* struct mofld_pinctrl - Intel Merrifield pinctrl private structure .pins = mofld_pins,
* @dev: Pointer to the device structure .npins = ARRAY_SIZE(mofld_pins),
* @lock: Lock to serialize register access .families = mofld_families,
* @pctldesc: Pin controller description .nfamilies = ARRAY_SIZE(mofld_families),
* @pctldev: Pointer to the pin controller device
* @families: Array of families this pinctrl handles
* @nfamilies: Number of families in the array
* @functions: Array of functions
* @nfunctions: Number of functions in the array
* @groups: Array of pin groups
* @ngroups: Number of groups in the array
* @pins: Array of pins this pinctrl controls
* @npins: Number of pins in the array
*/
struct mofld_pinctrl {
struct device *dev;
raw_spinlock_t lock;
struct pinctrl_desc pctldesc;
struct pinctrl_dev *pctldev;
/* Pin controller configuration */
const struct mofld_family *families;
size_t nfamilies;
const struct intel_function *functions;
size_t nfunctions;
const struct intel_pingroup *groups;
size_t ngroups;
const struct pinctrl_pin_desc *pins;
size_t npins;
}; };
#define pin_to_bufno(f, p) ((p) - (f)->pin_base)
static const struct mofld_family *mofld_get_family(struct mofld_pinctrl *mp, unsigned int pin)
{
const struct mofld_family *family;
unsigned int i;
for (i = 0; i < mp->nfamilies; i++) {
family = &mp->families[i];
if (pin >= family->pin_base &&
pin < family->pin_base + family->npins)
return family;
}
dev_warn(mp->dev, "failed to find family for pin %u\n", pin);
return NULL;
}
static bool mofld_buf_available(struct mofld_pinctrl *mp, unsigned int pin)
{
const struct mofld_family *family;
family = mofld_get_family(mp, pin);
if (!family)
return false;
return !family->protected;
}
static void __iomem *mofld_get_bufcfg(struct mofld_pinctrl *mp, unsigned int pin)
{
const struct mofld_family *family;
unsigned int bufno;
family = mofld_get_family(mp, pin);
if (!family)
return NULL;
bufno = pin_to_bufno(family, pin);
return family->regs + BUFCFG_OFFSET + bufno * 4;
}
static int mofld_read_bufcfg(struct mofld_pinctrl *mp, unsigned int pin, u32 *value)
{
void __iomem *bufcfg;
if (!mofld_buf_available(mp, pin))
return -EBUSY;
bufcfg = mofld_get_bufcfg(mp, pin);
*value = readl(bufcfg);
return 0;
}
static void mofld_update_bufcfg(struct mofld_pinctrl *mp, unsigned int pin, u32 bits, u32 mask)
{
void __iomem *bufcfg;
u32 value;
bufcfg = mofld_get_bufcfg(mp, pin);
value = readl(bufcfg);
value &= ~mask;
value |= bits & mask;
writel(value, bufcfg);
}
static int mofld_get_groups_count(struct pinctrl_dev *pctldev)
{
struct mofld_pinctrl *mp = pinctrl_dev_get_drvdata(pctldev);
return mp->ngroups;
}
static const char *mofld_get_group_name(struct pinctrl_dev *pctldev, unsigned int group)
{
struct mofld_pinctrl *mp = pinctrl_dev_get_drvdata(pctldev);
return mp->groups[group].grp.name;
}
static int mofld_get_group_pins(struct pinctrl_dev *pctldev, unsigned int group,
const unsigned int **pins, unsigned int *npins)
{
struct mofld_pinctrl *mp = pinctrl_dev_get_drvdata(pctldev);
*pins = mp->groups[group].grp.pins;
*npins = mp->groups[group].grp.npins;
return 0;
}
static void mofld_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
unsigned int pin)
{
struct mofld_pinctrl *mp = pinctrl_dev_get_drvdata(pctldev);
u32 value, mode;
int ret;
ret = mofld_read_bufcfg(mp, pin, &value);
if (ret) {
seq_puts(s, "not available");
return;
}
mode = (value & BUFCFG_PINMODE_MASK) >> BUFCFG_PINMODE_SHIFT;
if (mode == BUFCFG_PINMODE_GPIO)
seq_puts(s, "GPIO ");
else
seq_printf(s, "mode %d ", mode);
seq_printf(s, "0x%08x", value);
}
static const struct pinctrl_ops mofld_pinctrl_ops = {
.get_groups_count = mofld_get_groups_count,
.get_group_name = mofld_get_group_name,
.get_group_pins = mofld_get_group_pins,
.pin_dbg_show = mofld_pin_dbg_show,
};
static int mofld_get_functions_count(struct pinctrl_dev *pctldev)
{
struct mofld_pinctrl *mp = pinctrl_dev_get_drvdata(pctldev);
return mp->nfunctions;
}
static const char *mofld_get_function_name(struct pinctrl_dev *pctldev, unsigned int function)
{
struct mofld_pinctrl *mp = pinctrl_dev_get_drvdata(pctldev);
return mp->functions[function].func.name;
}
static int mofld_get_function_groups(struct pinctrl_dev *pctldev, unsigned int function,
const char * const **groups, unsigned int * const ngroups)
{
struct mofld_pinctrl *mp = pinctrl_dev_get_drvdata(pctldev);
*groups = mp->functions[function].func.groups;
*ngroups = mp->functions[function].func.ngroups;
return 0;
}
static int mofld_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int function,
unsigned int group)
{
struct mofld_pinctrl *mp = pinctrl_dev_get_drvdata(pctldev);
const struct intel_pingroup *grp = &mp->groups[group];
u32 bits = grp->mode << BUFCFG_PINMODE_SHIFT;
u32 mask = BUFCFG_PINMODE_MASK;
unsigned long flags;
unsigned int i;
/*
* All pins in the groups needs to be accessible and writable
* before we can enable the mux for this group.
*/
for (i = 0; i < grp->grp.npins; i++) {
if (!mofld_buf_available(mp, grp->grp.pins[i]))
return -EBUSY;
}
/* Now enable the mux setting for each pin in the group */
raw_spin_lock_irqsave(&mp->lock, flags);
for (i = 0; i < grp->grp.npins; i++)
mofld_update_bufcfg(mp, grp->grp.pins[i], bits, mask);
raw_spin_unlock_irqrestore(&mp->lock, flags);
return 0;
}
static int mofld_gpio_request_enable(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned int pin)
{
struct mofld_pinctrl *mp = pinctrl_dev_get_drvdata(pctldev);
u32 bits = BUFCFG_PINMODE_GPIO << BUFCFG_PINMODE_SHIFT;
u32 mask = BUFCFG_PINMODE_MASK;
unsigned long flags;
if (!mofld_buf_available(mp, pin))
return -EBUSY;
raw_spin_lock_irqsave(&mp->lock, flags);
mofld_update_bufcfg(mp, pin, bits, mask);
raw_spin_unlock_irqrestore(&mp->lock, flags);
return 0;
}
static const struct pinmux_ops mofld_pinmux_ops = {
.get_functions_count = mofld_get_functions_count,
.get_function_name = mofld_get_function_name,
.get_function_groups = mofld_get_function_groups,
.set_mux = mofld_pinmux_set_mux,
.gpio_request_enable = mofld_gpio_request_enable,
};
static int mofld_config_get(struct pinctrl_dev *pctldev, unsigned int pin,
unsigned long *config)
{
struct mofld_pinctrl *mp = pinctrl_dev_get_drvdata(pctldev);
enum pin_config_param param = pinconf_to_config_param(*config);
u32 value, term;
u16 arg = 0;
int ret;
ret = mofld_read_bufcfg(mp, pin, &value);
if (ret)
return -ENOTSUPP;
term = (value & BUFCFG_PUPD_VAL_MASK) >> BUFCFG_PUPD_VAL_SHIFT;
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
if (value & BUFCFG_Px_EN_MASK)
return -EINVAL;
break;
case PIN_CONFIG_BIAS_PULL_UP:
if ((value & BUFCFG_Px_EN_MASK) != BUFCFG_PU_EN)
return -EINVAL;
switch (term) {
case BUFCFG_PUPD_VAL_910:
arg = 910;
break;
case BUFCFG_PUPD_VAL_2K:
arg = 2000;
break;
case BUFCFG_PUPD_VAL_20K:
arg = 20000;
break;
case BUFCFG_PUPD_VAL_50K:
arg = 50000;
break;
}
break;
case PIN_CONFIG_BIAS_PULL_DOWN:
if ((value & BUFCFG_Px_EN_MASK) != BUFCFG_PD_EN)
return -EINVAL;
switch (term) {
case BUFCFG_PUPD_VAL_910:
arg = 910;
break;
case BUFCFG_PUPD_VAL_2K:
arg = 2000;
break;
case BUFCFG_PUPD_VAL_20K:
arg = 20000;
break;
case BUFCFG_PUPD_VAL_50K:
arg = 50000;
break;
}
break;
case PIN_CONFIG_DRIVE_PUSH_PULL:
if (value & BUFCFG_OD_EN)
return -EINVAL;
break;
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
if (!(value & BUFCFG_OD_EN))
return -EINVAL;
break;
case PIN_CONFIG_SLEW_RATE:
if (!(value & BUFCFG_SLEWSEL))
arg = 0;
else
arg = 1;
break;
default:
return -ENOTSUPP;
}
*config = pinconf_to_config_packed(param, arg);
return 0;
}
static int mofld_config_set_pin(struct mofld_pinctrl *mp, unsigned int pin,
unsigned long config)
{
unsigned int param = pinconf_to_config_param(config);
unsigned int arg = pinconf_to_config_argument(config);
u32 bits = 0, mask = 0;
unsigned long flags;
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
mask |= BUFCFG_Px_EN_MASK | BUFCFG_PUPD_VAL_MASK;
break;
case PIN_CONFIG_BIAS_PULL_UP:
mask |= BUFCFG_Px_EN_MASK | BUFCFG_PUPD_VAL_MASK;
bits |= BUFCFG_PU_EN;
switch (arg) {
case 50000:
bits |= BUFCFG_PUPD_VAL_50K << BUFCFG_PUPD_VAL_SHIFT;
break;
case 20000:
bits |= BUFCFG_PUPD_VAL_20K << BUFCFG_PUPD_VAL_SHIFT;
break;
case 2000:
bits |= BUFCFG_PUPD_VAL_2K << BUFCFG_PUPD_VAL_SHIFT;
break;
default:
return -EINVAL;
}
break;
case PIN_CONFIG_BIAS_PULL_DOWN:
mask |= BUFCFG_Px_EN_MASK | BUFCFG_PUPD_VAL_MASK;
bits |= BUFCFG_PD_EN;
switch (arg) {
case 50000:
bits |= BUFCFG_PUPD_VAL_50K << BUFCFG_PUPD_VAL_SHIFT;
break;
case 20000:
bits |= BUFCFG_PUPD_VAL_20K << BUFCFG_PUPD_VAL_SHIFT;
break;
case 2000:
bits |= BUFCFG_PUPD_VAL_2K << BUFCFG_PUPD_VAL_SHIFT;
break;
default:
return -EINVAL;
}
break;
case PIN_CONFIG_DRIVE_PUSH_PULL:
mask |= BUFCFG_OD_EN;
bits &= ~BUFCFG_OD_EN;
break;
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
mask |= BUFCFG_OD_EN;
bits |= BUFCFG_OD_EN;
break;
case PIN_CONFIG_SLEW_RATE:
mask |= BUFCFG_SLEWSEL;
if (arg)
bits |= BUFCFG_SLEWSEL;
break;
}
raw_spin_lock_irqsave(&mp->lock, flags);
mofld_update_bufcfg(mp, pin, bits, mask);
raw_spin_unlock_irqrestore(&mp->lock, flags);
return 0;
}
static int mofld_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
unsigned long *configs, unsigned int nconfigs)
{
struct mofld_pinctrl *mp = pinctrl_dev_get_drvdata(pctldev);
unsigned int i;
int ret;
if (!mofld_buf_available(mp, pin))
return -ENOTSUPP;
for (i = 0; i < nconfigs; i++) {
switch (pinconf_to_config_param(configs[i])) {
case PIN_CONFIG_BIAS_DISABLE:
case PIN_CONFIG_BIAS_PULL_UP:
case PIN_CONFIG_BIAS_PULL_DOWN:
case PIN_CONFIG_DRIVE_PUSH_PULL:
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
case PIN_CONFIG_SLEW_RATE:
ret = mofld_config_set_pin(mp, pin, configs[i]);
if (ret)
return ret;
break;
default:
return -ENOTSUPP;
}
}
return 0;
}
static int mofld_config_group_get(struct pinctrl_dev *pctldev, unsigned int group,
unsigned long *config)
{
const unsigned int *pins;
unsigned int npins;
int ret;
ret = mofld_get_group_pins(pctldev, group, &pins, &npins);
if (ret)
return ret;
ret = mofld_config_get(pctldev, pins[0], config);
if (ret)
return ret;
return 0;
}
static int mofld_config_group_set(struct pinctrl_dev *pctldev, unsigned int group,
unsigned long *configs, unsigned int num_configs)
{
const unsigned int *pins;
unsigned int npins;
int i, ret;
ret = mofld_get_group_pins(pctldev, group, &pins, &npins);
if (ret)
return ret;
for (i = 0; i < npins; i++) {
ret = mofld_config_set(pctldev, pins[i], configs, num_configs);
if (ret)
return ret;
}
return 0;
}
static const struct pinconf_ops mofld_pinconf_ops = {
.is_generic = true,
.pin_config_get = mofld_config_get,
.pin_config_set = mofld_config_set,
.pin_config_group_get = mofld_config_group_get,
.pin_config_group_set = mofld_config_group_set,
};
static const struct pinctrl_desc mofld_pinctrl_desc = {
.pctlops = &mofld_pinctrl_ops,
.pmxops = &mofld_pinmux_ops,
.confops = &mofld_pinconf_ops,
.owner = THIS_MODULE,
};
static int mofld_pinctrl_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct mofld_family *families;
struct mofld_pinctrl *mp;
void __iomem *regs;
size_t nfamilies;
unsigned int i;
mp = devm_kzalloc(dev, sizeof(*mp), GFP_KERNEL);
if (!mp)
return -ENOMEM;
mp->dev = dev;
raw_spin_lock_init(&mp->lock);
regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(regs))
return PTR_ERR(regs);
nfamilies = ARRAY_SIZE(mofld_families),
families = devm_kmemdup(dev, mofld_families, sizeof(mofld_families), GFP_KERNEL);
if (!families)
return -ENOMEM;
/* Splice memory resource by chunk per family */
for (i = 0; i < nfamilies; i++) {
struct mofld_family *family = &families[i];
family->regs = regs + family->barno * MOFLD_FAMILY_LEN;
}
mp->families = families;
mp->nfamilies = nfamilies;
mp->pctldesc = mofld_pinctrl_desc;
mp->pctldesc.name = dev_name(dev);
mp->pctldesc.pins = mofld_pins;
mp->pctldesc.npins = ARRAY_SIZE(mofld_pins);
mp->pctldev = devm_pinctrl_register(dev, &mp->pctldesc, mp);
if (IS_ERR(mp->pctldev))
return PTR_ERR(mp->pctldev);
platform_set_drvdata(pdev, mp);
return 0;
}
static const struct acpi_device_id mofld_acpi_table[] = { static const struct acpi_device_id mofld_acpi_table[] = {
{ "INTC1003" }, { "INTC1003", (kernel_ulong_t)&mofld_soc_data },
{ } { }
}; };
MODULE_DEVICE_TABLE(acpi, mofld_acpi_table); MODULE_DEVICE_TABLE(acpi, mofld_acpi_table);
static struct platform_driver mofld_pinctrl_driver = { static struct platform_driver mofld_pinctrl_driver = {
.probe = mofld_pinctrl_probe, .probe = devm_tng_pinctrl_probe,
.driver = { .driver = {
.name = "pinctrl-moorefield", .name = "pinctrl-moorefield",
.acpi_match_table = mofld_acpi_table, .acpi_match_table = mofld_acpi_table,
@ -924,3 +341,4 @@ MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
MODULE_DESCRIPTION("Intel Moorefield SoC pinctrl driver"); MODULE_DESCRIPTION("Intel Moorefield SoC pinctrl driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:pinctrl-moorefield"); MODULE_ALIAS("platform:pinctrl-moorefield");
MODULE_IMPORT_NS(PINCTRL_TANGIER);

View File

@ -606,3 +606,4 @@ MODULE_AUTHOR("Mathias Nyman <mathias.nyman@linux.intel.com>");
MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>"); MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
MODULE_DESCRIPTION("Intel Sunrisepoint PCH pinctrl/GPIO driver"); MODULE_DESCRIPTION("Intel Sunrisepoint PCH pinctrl/GPIO driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_IMPORT_NS(PINCTRL_INTEL);

View File

@ -0,0 +1,589 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Intel Tangier pinctrl driver
*
* Copyright (C) 2016, 2023 Intel Corporation
*
* Authors: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
* Raag Jadav <raag.jadav@intel.com>
*/
#include <linux/bits.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/export.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/overflow.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/seq_file.h>
#include <linux/spinlock.h>
#include <linux/types.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include "../core.h"
#include "pinctrl-intel.h"
#include "pinctrl-tangier.h"
#define SLEW_OFFSET 0x000
#define BUFCFG_OFFSET 0x100
#define MISC_OFFSET 0x300
#define BUFCFG_PINMODE_SHIFT 0
#define BUFCFG_PINMODE_MASK GENMASK(2, 0)
#define BUFCFG_PINMODE_GPIO 0
#define BUFCFG_PUPD_VAL_SHIFT 4
#define BUFCFG_PUPD_VAL_MASK GENMASK(5, 4)
#define BUFCFG_PUPD_VAL_2K 0
#define BUFCFG_PUPD_VAL_20K 1
#define BUFCFG_PUPD_VAL_50K 2
#define BUFCFG_PUPD_VAL_910 3
#define BUFCFG_PU_EN BIT(8)
#define BUFCFG_PD_EN BIT(9)
#define BUFCFG_Px_EN_MASK GENMASK(9, 8)
#define BUFCFG_SLEWSEL BIT(10)
#define BUFCFG_OVINEN BIT(12)
#define BUFCFG_OVINEN_EN BIT(13)
#define BUFCFG_OVINEN_MASK GENMASK(13, 12)
#define BUFCFG_OVOUTEN BIT(14)
#define BUFCFG_OVOUTEN_EN BIT(15)
#define BUFCFG_OVOUTEN_MASK GENMASK(15, 14)
#define BUFCFG_INDATAOV_VAL BIT(16)
#define BUFCFG_INDATAOV_EN BIT(17)
#define BUFCFG_INDATAOV_MASK GENMASK(17, 16)
#define BUFCFG_OUTDATAOV_VAL BIT(18)
#define BUFCFG_OUTDATAOV_EN BIT(19)
#define BUFCFG_OUTDATAOV_MASK GENMASK(19, 18)
#define BUFCFG_OD_EN BIT(21)
#define pin_to_bufno(f, p) ((p) - (f)->pin_base)
static const struct tng_family *tng_get_family(struct tng_pinctrl *tp,
unsigned int pin)
{
const struct tng_family *family;
unsigned int i;
for (i = 0; i < tp->nfamilies; i++) {
family = &tp->families[i];
if (pin >= family->pin_base &&
pin < family->pin_base + family->npins)
return family;
}
dev_warn(tp->dev, "failed to find family for pin %u\n", pin);
return NULL;
}
static bool tng_buf_available(struct tng_pinctrl *tp, unsigned int pin)
{
const struct tng_family *family;
family = tng_get_family(tp, pin);
if (!family)
return false;
return !family->protected;
}
static void __iomem *tng_get_bufcfg(struct tng_pinctrl *tp, unsigned int pin)
{
const struct tng_family *family;
unsigned int bufno;
family = tng_get_family(tp, pin);
if (!family)
return NULL;
bufno = pin_to_bufno(family, pin);
return family->regs + BUFCFG_OFFSET + bufno * 4;
}
static int tng_read_bufcfg(struct tng_pinctrl *tp, unsigned int pin, u32 *value)
{
void __iomem *bufcfg;
if (!tng_buf_available(tp, pin))
return -EBUSY;
bufcfg = tng_get_bufcfg(tp, pin);
*value = readl(bufcfg);
return 0;
}
static void tng_update_bufcfg(struct tng_pinctrl *tp, unsigned int pin,
u32 bits, u32 mask)
{
void __iomem *bufcfg;
u32 value;
bufcfg = tng_get_bufcfg(tp, pin);
value = readl(bufcfg);
value = (value & ~mask) | (bits & mask);
writel(value, bufcfg);
}
static int tng_get_groups_count(struct pinctrl_dev *pctldev)
{
struct tng_pinctrl *tp = pinctrl_dev_get_drvdata(pctldev);
return tp->ngroups;
}
static const char *tng_get_group_name(struct pinctrl_dev *pctldev,
unsigned int group)
{
struct tng_pinctrl *tp = pinctrl_dev_get_drvdata(pctldev);
return tp->groups[group].grp.name;
}
static int tng_get_group_pins(struct pinctrl_dev *pctldev, unsigned int group,
const unsigned int **pins, unsigned int *npins)
{
struct tng_pinctrl *tp = pinctrl_dev_get_drvdata(pctldev);
*pins = tp->groups[group].grp.pins;
*npins = tp->groups[group].grp.npins;
return 0;
}
static void tng_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
unsigned int pin)
{
struct tng_pinctrl *tp = pinctrl_dev_get_drvdata(pctldev);
u32 value, mode;
int ret;
ret = tng_read_bufcfg(tp, pin, &value);
if (ret) {
seq_puts(s, "not available");
return;
}
mode = (value & BUFCFG_PINMODE_MASK) >> BUFCFG_PINMODE_SHIFT;
if (mode == BUFCFG_PINMODE_GPIO)
seq_puts(s, "GPIO ");
else
seq_printf(s, "mode %d ", mode);
seq_printf(s, "0x%08x", value);
}
static const struct pinctrl_ops tng_pinctrl_ops = {
.get_groups_count = tng_get_groups_count,
.get_group_name = tng_get_group_name,
.get_group_pins = tng_get_group_pins,
.pin_dbg_show = tng_pin_dbg_show,
};
static int tng_get_functions_count(struct pinctrl_dev *pctldev)
{
struct tng_pinctrl *tp = pinctrl_dev_get_drvdata(pctldev);
return tp->nfunctions;
}
static const char *tng_get_function_name(struct pinctrl_dev *pctldev,
unsigned int function)
{
struct tng_pinctrl *tp = pinctrl_dev_get_drvdata(pctldev);
return tp->functions[function].func.name;
}
static int tng_get_function_groups(struct pinctrl_dev *pctldev,
unsigned int function,
const char * const **groups,
unsigned int * const ngroups)
{
struct tng_pinctrl *tp = pinctrl_dev_get_drvdata(pctldev);
*groups = tp->functions[function].func.groups;
*ngroups = tp->functions[function].func.ngroups;
return 0;
}
static int tng_pinmux_set_mux(struct pinctrl_dev *pctldev,
unsigned int function,
unsigned int group)
{
struct tng_pinctrl *tp = pinctrl_dev_get_drvdata(pctldev);
const struct intel_pingroup *grp = &tp->groups[group];
u32 bits = grp->mode << BUFCFG_PINMODE_SHIFT;
u32 mask = BUFCFG_PINMODE_MASK;
unsigned long flags;
unsigned int i;
/*
* All pins in the groups needs to be accessible and writable
* before we can enable the mux for this group.
*/
for (i = 0; i < grp->grp.npins; i++) {
if (!tng_buf_available(tp, grp->grp.pins[i]))
return -EBUSY;
}
/* Now enable the mux setting for each pin in the group */
raw_spin_lock_irqsave(&tp->lock, flags);
for (i = 0; i < grp->grp.npins; i++)
tng_update_bufcfg(tp, grp->grp.pins[i], bits, mask);
raw_spin_unlock_irqrestore(&tp->lock, flags);
return 0;
}
static int tng_gpio_request_enable(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned int pin)
{
struct tng_pinctrl *tp = pinctrl_dev_get_drvdata(pctldev);
u32 bits = BUFCFG_PINMODE_GPIO << BUFCFG_PINMODE_SHIFT;
u32 mask = BUFCFG_PINMODE_MASK;
unsigned long flags;
if (!tng_buf_available(tp, pin))
return -EBUSY;
raw_spin_lock_irqsave(&tp->lock, flags);
tng_update_bufcfg(tp, pin, bits, mask);
raw_spin_unlock_irqrestore(&tp->lock, flags);
return 0;
}
static const struct pinmux_ops tng_pinmux_ops = {
.get_functions_count = tng_get_functions_count,
.get_function_name = tng_get_function_name,
.get_function_groups = tng_get_function_groups,
.set_mux = tng_pinmux_set_mux,
.gpio_request_enable = tng_gpio_request_enable,
};
static int tng_config_get(struct pinctrl_dev *pctldev, unsigned int pin,
unsigned long *config)
{
struct tng_pinctrl *tp = pinctrl_dev_get_drvdata(pctldev);
enum pin_config_param param = pinconf_to_config_param(*config);
u32 value, term;
u16 arg = 0;
int ret;
ret = tng_read_bufcfg(tp, pin, &value);
if (ret)
return -ENOTSUPP;
term = (value & BUFCFG_PUPD_VAL_MASK) >> BUFCFG_PUPD_VAL_SHIFT;
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
if (value & BUFCFG_Px_EN_MASK)
return -EINVAL;
break;
case PIN_CONFIG_BIAS_PULL_UP:
if ((value & BUFCFG_Px_EN_MASK) != BUFCFG_PU_EN)
return -EINVAL;
switch (term) {
case BUFCFG_PUPD_VAL_910:
arg = 910;
break;
case BUFCFG_PUPD_VAL_2K:
arg = 2000;
break;
case BUFCFG_PUPD_VAL_20K:
arg = 20000;
break;
case BUFCFG_PUPD_VAL_50K:
arg = 50000;
break;
}
break;
case PIN_CONFIG_BIAS_PULL_DOWN:
if ((value & BUFCFG_Px_EN_MASK) != BUFCFG_PD_EN)
return -EINVAL;
switch (term) {
case BUFCFG_PUPD_VAL_910:
arg = 910;
break;
case BUFCFG_PUPD_VAL_2K:
arg = 2000;
break;
case BUFCFG_PUPD_VAL_20K:
arg = 20000;
break;
case BUFCFG_PUPD_VAL_50K:
arg = 50000;
break;
}
break;
case PIN_CONFIG_DRIVE_PUSH_PULL:
if (value & BUFCFG_OD_EN)
return -EINVAL;
break;
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
if (!(value & BUFCFG_OD_EN))
return -EINVAL;
break;
case PIN_CONFIG_SLEW_RATE:
if (value & BUFCFG_SLEWSEL)
arg = 1;
break;
default:
return -ENOTSUPP;
}
*config = pinconf_to_config_packed(param, arg);
return 0;
}
static int tng_config_set_pin(struct tng_pinctrl *tp, unsigned int pin,
unsigned long config)
{
unsigned int param = pinconf_to_config_param(config);
unsigned int arg = pinconf_to_config_argument(config);
u32 mask, term, value = 0;
unsigned long flags;
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
mask = BUFCFG_Px_EN_MASK | BUFCFG_PUPD_VAL_MASK;
break;
case PIN_CONFIG_BIAS_PULL_UP:
/* Set default strength value in case none is given */
if (arg == 1)
arg = 20000;
switch (arg) {
case 50000:
term = BUFCFG_PUPD_VAL_50K;
break;
case 20000:
term = BUFCFG_PUPD_VAL_20K;
break;
case 2000:
term = BUFCFG_PUPD_VAL_2K;
break;
default:
return -EINVAL;
}
mask = BUFCFG_Px_EN_MASK | BUFCFG_PUPD_VAL_MASK;
value = BUFCFG_PU_EN | (term << BUFCFG_PUPD_VAL_SHIFT);
break;
case PIN_CONFIG_BIAS_PULL_DOWN:
/* Set default strength value in case none is given */
if (arg == 1)
arg = 20000;
switch (arg) {
case 50000:
term = BUFCFG_PUPD_VAL_50K;
break;
case 20000:
term = BUFCFG_PUPD_VAL_20K;
break;
case 2000:
term = BUFCFG_PUPD_VAL_2K;
break;
default:
return -EINVAL;
}
mask = BUFCFG_Px_EN_MASK | BUFCFG_PUPD_VAL_MASK;
value = BUFCFG_PD_EN | (term << BUFCFG_PUPD_VAL_SHIFT);
break;
case PIN_CONFIG_DRIVE_PUSH_PULL:
mask = BUFCFG_OD_EN;
break;
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
mask = BUFCFG_OD_EN;
value = BUFCFG_OD_EN;
break;
case PIN_CONFIG_SLEW_RATE:
mask = BUFCFG_SLEWSEL;
if (arg)
value = BUFCFG_SLEWSEL;
break;
default:
return -EINVAL;
}
raw_spin_lock_irqsave(&tp->lock, flags);
tng_update_bufcfg(tp, pin, value, mask);
raw_spin_unlock_irqrestore(&tp->lock, flags);
return 0;
}
static int tng_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
unsigned long *configs, unsigned int nconfigs)
{
struct tng_pinctrl *tp = pinctrl_dev_get_drvdata(pctldev);
unsigned int i;
int ret;
if (!tng_buf_available(tp, pin))
return -ENOTSUPP;
for (i = 0; i < nconfigs; i++) {
switch (pinconf_to_config_param(configs[i])) {
case PIN_CONFIG_BIAS_DISABLE:
case PIN_CONFIG_BIAS_PULL_UP:
case PIN_CONFIG_BIAS_PULL_DOWN:
case PIN_CONFIG_DRIVE_PUSH_PULL:
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
case PIN_CONFIG_SLEW_RATE:
ret = tng_config_set_pin(tp, pin, configs[i]);
if (ret)
return ret;
break;
default:
return -ENOTSUPP;
}
}
return 0;
}
static int tng_config_group_get(struct pinctrl_dev *pctldev,
unsigned int group, unsigned long *config)
{
const unsigned int *pins;
unsigned int npins;
int ret;
ret = tng_get_group_pins(pctldev, group, &pins, &npins);
if (ret)
return ret;
return tng_config_get(pctldev, pins[0], config);
}
static int tng_config_group_set(struct pinctrl_dev *pctldev,
unsigned int group, unsigned long *configs,
unsigned int num_configs)
{
const unsigned int *pins;
unsigned int npins;
int i, ret;
ret = tng_get_group_pins(pctldev, group, &pins, &npins);
if (ret)
return ret;
for (i = 0; i < npins; i++) {
ret = tng_config_set(pctldev, pins[i], configs, num_configs);
if (ret)
return ret;
}
return 0;
}
static const struct pinconf_ops tng_pinconf_ops = {
.is_generic = true,
.pin_config_get = tng_config_get,
.pin_config_set = tng_config_set,
.pin_config_group_get = tng_config_group_get,
.pin_config_group_set = tng_config_group_set,
};
static const struct pinctrl_desc tng_pinctrl_desc = {
.pctlops = &tng_pinctrl_ops,
.pmxops = &tng_pinmux_ops,
.confops = &tng_pinconf_ops,
.owner = THIS_MODULE,
};
static int tng_pinctrl_probe(struct platform_device *pdev,
const struct tng_pinctrl *data)
{
struct device *dev = &pdev->dev;
struct tng_family *families;
struct tng_pinctrl *tp;
size_t families_len;
void __iomem *regs;
unsigned int i;
tp = devm_kmemdup(dev, data, sizeof(*data), GFP_KERNEL);
if (!tp)
return -ENOMEM;
tp->dev = dev;
raw_spin_lock_init(&tp->lock);
regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(regs))
return PTR_ERR(regs);
/*
* Make a copy of the families which we can use to hold pointers
* to the registers.
*/
families_len = size_mul(sizeof(*families), tp->nfamilies);
families = devm_kmemdup(dev, tp->families, families_len, GFP_KERNEL);
if (!families)
return -ENOMEM;
/* Splice memory resource by chunk per family */
for (i = 0; i < tp->nfamilies; i++) {
struct tng_family *family = &families[i];
family->regs = regs + family->barno * TNG_FAMILY_LEN;
}
tp->families = families;
tp->pctldesc = tng_pinctrl_desc;
tp->pctldesc.name = dev_name(dev);
tp->pctldesc.pins = tp->pins;
tp->pctldesc.npins = tp->npins;
tp->pctldev = devm_pinctrl_register(dev, &tp->pctldesc, tp);
if (IS_ERR(tp->pctldev))
return dev_err_probe(dev, PTR_ERR(tp->pctldev),
"failed to register pinctrl driver\n");
return 0;
}
int devm_tng_pinctrl_probe(struct platform_device *pdev)
{
const struct tng_pinctrl *data;
data = device_get_match_data(&pdev->dev);
if (!data)
return -ENODATA;
return tng_pinctrl_probe(pdev, data);
}
EXPORT_SYMBOL_NS_GPL(devm_tng_pinctrl_probe, PINCTRL_TANGIER);
MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
MODULE_AUTHOR("Raag Jadav <raag.jadav@intel.com>");
MODULE_DESCRIPTION("Intel Tangier pinctrl driver");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,92 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Intel Tangier pinctrl functions
*
* Copyright (C) 2016, 2023 Intel Corporation
*
* Authors: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
* Raag Jadav <raag.jadav@intel.com>
*/
#ifndef PINCTRL_TANGIER_H
#define PINCTRL_TANGIER_H
#include <linux/spinlock_types.h>
#include <linux/types.h>
#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-intel.h"
struct device;
struct platform_device;
#define TNG_FAMILY_NR 64
#define TNG_FAMILY_LEN 0x400
/**
* struct tng_family - Tangier pin family description
* @barno: MMIO BAR number where registers for this family reside
* @pin_base: Starting pin of pins in this family
* @npins: Number of pins in this family
* @protected: True if family is protected by access
* @regs: Family specific common registers
*/
struct tng_family {
unsigned int barno;
unsigned int pin_base;
size_t npins;
bool protected;
void __iomem *regs;
};
#define TNG_FAMILY(b, s, e) \
{ \
.barno = (b), \
.pin_base = (s), \
.npins = (e) - (s) + 1, \
}
#define TNG_FAMILY_PROTECTED(b, s, e) \
{ \
.barno = (b), \
.pin_base = (s), \
.npins = (e) - (s) + 1, \
.protected = true, \
}
/**
* struct tng_pinctrl - Tangier 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
* @families: Array of families this pinctrl handles
* @nfamilies: Number of families in the array
* @functions: Array of functions
* @nfunctions: Number of functions in the array
* @groups: Array of pin groups
* @ngroups: Number of groups in the array
* @pins: Array of pins this pinctrl controls
* @npins: Number of pins in the array
*/
struct tng_pinctrl {
struct device *dev;
raw_spinlock_t lock;
struct pinctrl_desc pctldesc;
struct pinctrl_dev *pctldev;
/* Pin controller configuration */
const struct tng_family *families;
size_t nfamilies;
const struct intel_function *functions;
size_t nfunctions;
const struct intel_pingroup *groups;
size_t ngroups;
const struct pinctrl_pin_desc *pins;
size_t npins;
};
int devm_tng_pinctrl_probe(struct platform_device *pdev);
#endif /* PINCTRL_TANGIER_H */

View File

@ -753,10 +753,10 @@ static struct platform_driver tgl_pinctrl_driver = {
.pm = &tgl_pinctrl_pm_ops, .pm = &tgl_pinctrl_pm_ops,
}, },
}; };
module_platform_driver(tgl_pinctrl_driver); module_platform_driver(tgl_pinctrl_driver);
MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>"); MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>"); MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
MODULE_DESCRIPTION("Intel Tiger Lake PCH pinctrl/GPIO driver"); MODULE_DESCRIPTION("Intel Tiger Lake PCH pinctrl/GPIO driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_IMPORT_NS(PINCTRL_INTEL);

View File

@ -1011,7 +1011,6 @@ static int armada_37xx_pinctrl_register(struct platform_device *pdev,
return 0; return 0;
} }
#if defined(CONFIG_PM)
static int armada_3700_pinctrl_suspend(struct device *dev) static int armada_3700_pinctrl_suspend(struct device *dev)
{ {
struct armada_37xx_pinctrl *info = dev_get_drvdata(dev); struct armada_37xx_pinctrl *info = dev_get_drvdata(dev);
@ -1105,15 +1104,8 @@ static int armada_3700_pinctrl_resume(struct device *dev)
* Since pinctrl is an infrastructure module, its resume should be issued prior * Since pinctrl is an infrastructure module, its resume should be issued prior
* to other IO drivers. * to other IO drivers.
*/ */
static const struct dev_pm_ops armada_3700_pinctrl_pm_ops = { static DEFINE_NOIRQ_DEV_PM_OPS(armada_3700_pinctrl_pm_ops,
.suspend_noirq = armada_3700_pinctrl_suspend, armada_3700_pinctrl_suspend, armada_3700_pinctrl_resume);
.resume_noirq = armada_3700_pinctrl_resume,
};
#define PINCTRL_ARMADA_37XX_DEV_PM_OPS (&armada_3700_pinctrl_pm_ops)
#else
#define PINCTRL_ARMADA_37XX_DEV_PM_OPS NULL
#endif /* CONFIG_PM */
static const struct of_device_id armada_37xx_pinctrl_of_match[] = { static const struct of_device_id armada_37xx_pinctrl_of_match[] = {
{ {
@ -1180,7 +1172,7 @@ static struct platform_driver armada_37xx_pinctrl_driver = {
.driver = { .driver = {
.name = "armada-37xx-pinctrl", .name = "armada-37xx-pinctrl",
.of_match_table = armada_37xx_pinctrl_of_match, .of_match_table = armada_37xx_pinctrl_of_match,
.pm = PINCTRL_ARMADA_37XX_DEV_PM_OPS, .pm = pm_sleep_ptr(&armada_3700_pinctrl_pm_ops),
}, },
}; };

View File

@ -1657,7 +1657,7 @@ static int gpio_irq_set_wake(struct irq_data *d, unsigned state)
return 0; return 0;
} }
static int __maybe_unused at91_gpio_suspend(struct device *dev) static int at91_gpio_suspend(struct device *dev)
{ {
struct at91_gpio_chip *at91_chip = dev_get_drvdata(dev); struct at91_gpio_chip *at91_chip = dev_get_drvdata(dev);
void __iomem *pio = at91_chip->regbase; void __iomem *pio = at91_chip->regbase;
@ -1675,7 +1675,7 @@ static int __maybe_unused at91_gpio_suspend(struct device *dev)
return 0; return 0;
} }
static int __maybe_unused at91_gpio_resume(struct device *dev) static int at91_gpio_resume(struct device *dev)
{ {
struct at91_gpio_chip *at91_chip = dev_get_drvdata(dev); struct at91_gpio_chip *at91_chip = dev_get_drvdata(dev);
void __iomem *pio = at91_chip->regbase; void __iomem *pio = at91_chip->regbase;
@ -1903,15 +1903,13 @@ static int at91_gpio_probe(struct platform_device *pdev)
return 0; return 0;
} }
static const struct dev_pm_ops at91_gpio_pm_ops = { static DEFINE_NOIRQ_DEV_PM_OPS(at91_gpio_pm_ops, at91_gpio_suspend, at91_gpio_resume);
NOIRQ_SYSTEM_SLEEP_PM_OPS(at91_gpio_suspend, at91_gpio_resume)
};
static struct platform_driver at91_gpio_driver = { static struct platform_driver at91_gpio_driver = {
.driver = { .driver = {
.name = "gpio-at91", .name = "gpio-at91",
.of_match_table = at91_gpio_of_match, .of_match_table = at91_gpio_of_match,
.pm = pm_ptr(&at91_gpio_pm_ops), .pm = pm_sleep_ptr(&at91_gpio_pm_ops),
}, },
.probe = at91_gpio_probe, .probe = at91_gpio_probe,
}; };

View File

@ -648,7 +648,7 @@ static const struct of_device_id sh_pfc_of_table[] = {
}; };
#endif #endif
#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM_PSCI_FW) #if defined(CONFIG_ARM_PSCI_FW)
static void sh_pfc_nop_reg(struct sh_pfc *pfc, u32 reg, unsigned int idx) static void sh_pfc_nop_reg(struct sh_pfc *pfc, u32 reg, unsigned int idx)
{ {
} }
@ -731,15 +731,13 @@ static int sh_pfc_resume_noirq(struct device *dev)
sh_pfc_walk_regs(pfc, sh_pfc_restore_reg); sh_pfc_walk_regs(pfc, sh_pfc_restore_reg);
return 0; return 0;
} }
static const struct dev_pm_ops sh_pfc_pm = {
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(sh_pfc_suspend_noirq, sh_pfc_resume_noirq)
};
#define DEV_PM_OPS &sh_pfc_pm
#else #else
static int sh_pfc_suspend_init(struct sh_pfc *pfc) { return 0; } static int sh_pfc_suspend_init(struct sh_pfc *pfc) { return 0; }
#define DEV_PM_OPS NULL static int sh_pfc_suspend_noirq(struct device *dev) { return 0; }
#endif /* CONFIG_PM_SLEEP && CONFIG_ARM_PSCI_FW */ static int sh_pfc_resume_noirq(struct device *dev) { return 0; }
#endif /* CONFIG_ARM_PSCI_FW */
static DEFINE_NOIRQ_DEV_PM_OPS(sh_pfc_pm, sh_pfc_suspend_noirq, sh_pfc_resume_noirq);
#ifdef DEBUG #ifdef DEBUG
#define SH_PFC_MAX_REGS 300 #define SH_PFC_MAX_REGS 300
@ -1417,7 +1415,7 @@ static struct platform_driver sh_pfc_driver = {
.driver = { .driver = {
.name = DRV_NAME, .name = DRV_NAME,
.of_match_table = of_match_ptr(sh_pfc_of_table), .of_match_table = of_match_ptr(sh_pfc_of_table),
.pm = DEV_PM_OPS, .pm = pm_sleep_ptr(&sh_pfc_pm),
}, },
}; };

View File

@ -762,10 +762,7 @@ static int tegra_pinctrl_resume(struct device *dev)
return 0; return 0;
} }
const struct dev_pm_ops tegra_pinctrl_pm = { DEFINE_NOIRQ_DEV_PM_OPS(tegra_pinctrl_pm, tegra_pinctrl_suspend, tegra_pinctrl_resume);
.suspend_noirq = &tegra_pinctrl_suspend,
.resume_noirq = &tegra_pinctrl_resume
};
static bool tegra_pinctrl_gpio_node_has_range(struct tegra_pmx *pmx) static bool tegra_pinctrl_gpio_node_has_range(struct tegra_pmx *pmx)
{ {

View File

@ -1570,7 +1570,7 @@ static struct platform_driver tegra210_pinctrl_driver = {
.driver = { .driver = {
.name = "tegra210-pinctrl", .name = "tegra210-pinctrl",
.of_match_table = tegra210_pinctrl_of_match, .of_match_table = tegra210_pinctrl_of_match,
.pm = &tegra_pinctrl_pm, .pm = pm_sleep_ptr(&tegra_pinctrl_pm),
}, },
.probe = tegra210_pinctrl_probe, .probe = tegra210_pinctrl_probe,
}; };

View File

@ -448,6 +448,15 @@ const struct dev_pm_ops __maybe_unused name = { \
SET_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) \ SET_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) \
} }
/*
* Use this if you want to have the suspend and resume callbacks be called
* with IRQs disabled.
*/
#define DEFINE_NOIRQ_DEV_PM_OPS(name, suspend_fn, resume_fn) \
const struct dev_pm_ops name = { \
NOIRQ_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \
}
#define pm_ptr(_ptr) PTR_IF(IS_ENABLED(CONFIG_PM), (_ptr)) #define pm_ptr(_ptr) PTR_IF(IS_ENABLED(CONFIG_PM), (_ptr))
#define pm_sleep_ptr(_ptr) PTR_IF(IS_ENABLED(CONFIG_PM_SLEEP), (_ptr)) #define pm_sleep_ptr(_ptr) PTR_IF(IS_ENABLED(CONFIG_PM_SLEEP), (_ptr))