intel-pinctrl for v6.12-1
* Enable High Impedance pin configuration support for Intel pin control * Miscellaneous small improvements here and there The following is an automated git shortlog grouped by driver: baytrail: - Drop duplicate return statement intel: - Constify struct intel_pinctrl parameter - Inline intel_gpio_community_irq_handler() - Introduce for_each_intel_gpio_group() helper et al. - Constify intel_get_community() returned object - Implement high impedance support - Add __intel_gpio_get_direction() helper - Refactor __intel_gpio_set_direction() to be more useful - Move debounce validation out of the lock -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEhiZOUlnC9oKN3n3AmT3/83c5Sy0FAmbgAl8ACgkQmT3/83c5 Sy3XhQ//WfkhNv73IVvGPlKLI4s6A43xINEZ/8gVNeukaOGIi54xu3wlV5QevDOS 6MacKg0g0ZUo1KQXp86o54LqvCfOLklFzJsiWkYXqqImRvuA+5OuP4fVOv3XV9Ga i1b07A4vFamHwzUKt5kTYwhPOcqNzwYmPgU3jcArpANFs3lahVA9zCCzyXURTNnQ UH546mEqDezH2m5WgDHATBakSRJJr9bsVYIwAO/8OOz+V75Spmag0vJgWY/9QQms 3mUoJmTLOQbaDUqVqvTRU0uovgUlYXIOJS2EWLqnFBcK78fPZ1CDw0Vn8P6uo1km /FGcNmoDyXwW6TmI+CyHgiYIItjSYPE6YpxQZtIiGxA79bZwvBO7QA/7CYPniu/i WyKiKLUOYnvKTqsr9hKOYvHGV74hjRb0EuycnEyw0SCtsoxWlrNnuP4CG22X9O0+ OvfD3jMAFSAmYooifK0CZyi+IFphFpTUmy+fq+hT6MAH9H3uQ88QWThrw+4hA5O0 rNPtwvL0WoK+4v8twQbOSRVd63J20oMGL7+nGnymnO5EA/XLVIlCSBFQhhNBKC3/ OeWlyP/v+n6KnWNY4Wo9daBgF6Vej0B/9E5Z46mOKIDO5Q9iIzG4bOh/iwv9C/7Q BCnbOYiXJyLZLOJ7k9AuE0DfeYzIZsNIyDwximc8wus937YE2/g= =Z/p4 -----END PGP SIGNATURE----- Merge tag 'intel-pinctrl-v6.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pinctrl/intel into devel intel-pinctrl for v6.12-1 * Enable High Impedance pin configuration support for Intel pin control * Miscellaneous small improvements here and there The following is an automated git shortlog grouped by driver: baytrail: - Drop duplicate return statement intel: - Constify struct intel_pinctrl parameter - Inline intel_gpio_community_irq_handler() - Introduce for_each_intel_gpio_group() helper et al. - Constify intel_get_community() returned object - Implement high impedance support - Add __intel_gpio_get_direction() helper - Refactor __intel_gpio_set_direction() to be more useful - Move debounce validation out of the lock Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
commit
264c13114b
@ -560,9 +560,10 @@ static DEFINE_RAW_SPINLOCK(byt_lock);
|
||||
static void __iomem *byt_gpio_reg(struct intel_pinctrl *vg, unsigned int offset,
|
||||
int reg)
|
||||
{
|
||||
struct intel_community *comm = intel_get_community(vg, offset);
|
||||
const struct intel_community *comm;
|
||||
u32 reg_offset;
|
||||
|
||||
comm = intel_get_community(vg, offset);
|
||||
if (!comm)
|
||||
return NULL;
|
||||
|
||||
@ -1541,10 +1542,8 @@ static int byt_gpio_probe(struct intel_pinctrl *vg)
|
||||
}
|
||||
|
||||
ret = devm_gpiochip_add_data(vg->dev, gc, vg);
|
||||
if (ret) {
|
||||
if (ret)
|
||||
dev_err(vg->dev, "failed adding byt-gpio chip\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -70,6 +70,12 @@
|
||||
#define PADCFG0_PMODE_SHIFT 10
|
||||
#define PADCFG0_PMODE_MASK GENMASK(13, 10)
|
||||
#define PADCFG0_PMODE_GPIO 0
|
||||
#define PADCFG0_GPIODIS_SHIFT 8
|
||||
#define PADCFG0_GPIODIS_MASK GENMASK(9, 8)
|
||||
#define PADCFG0_GPIODIS_NONE 0
|
||||
#define PADCFG0_GPIODIS_OUTPUT 1
|
||||
#define PADCFG0_GPIODIS_INPUT 2
|
||||
#define PADCFG0_GPIODIS_FULL 3
|
||||
#define PADCFG0_GPIORXDIS BIT(9)
|
||||
#define PADCFG0_GPIOTXDIS BIT(8)
|
||||
#define PADCFG0_GPIORXSTATE BIT(1)
|
||||
@ -108,13 +114,30 @@ struct intel_community_context {
|
||||
#define pin_to_padno(c, p) ((p) - (c)->pin_base)
|
||||
#define padgroup_offset(g, p) ((p) - (g)->base)
|
||||
|
||||
struct intel_community *intel_get_community(struct intel_pinctrl *pctrl, unsigned int pin)
|
||||
{
|
||||
struct intel_community *community;
|
||||
int i;
|
||||
#define for_each_intel_pin_community(pctrl, community) \
|
||||
for (unsigned int __ci = 0; \
|
||||
__ci < pctrl->ncommunities && (community = &pctrl->communities[__ci]); \
|
||||
__ci++) \
|
||||
|
||||
for (i = 0; i < pctrl->ncommunities; i++) {
|
||||
community = &pctrl->communities[i];
|
||||
#define for_each_intel_community_pad_group(community, grp) \
|
||||
for (unsigned int __gi = 0; \
|
||||
__gi < community->ngpps && (grp = &community->gpps[__gi]); \
|
||||
__gi++) \
|
||||
|
||||
#define for_each_intel_pad_group(pctrl, community, grp) \
|
||||
for_each_intel_pin_community(pctrl, community) \
|
||||
for_each_intel_community_pad_group(community, grp)
|
||||
|
||||
#define for_each_intel_gpio_group(pctrl, community, grp) \
|
||||
for_each_intel_pad_group(pctrl, community, grp) \
|
||||
if (grp->gpio_base == INTEL_GPIO_BASE_NOMAP) {} else
|
||||
|
||||
const struct intel_community *intel_get_community(const struct intel_pinctrl *pctrl,
|
||||
unsigned int pin)
|
||||
{
|
||||
const struct intel_community *community;
|
||||
|
||||
for_each_intel_pin_community(pctrl, community) {
|
||||
if (pin >= community->pin_base &&
|
||||
pin < community->pin_base + community->npins)
|
||||
return community;
|
||||
@ -129,11 +152,9 @@ static const struct intel_padgroup *
|
||||
intel_community_get_padgroup(const struct intel_community *community,
|
||||
unsigned int pin)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < community->ngpps; i++) {
|
||||
const struct intel_padgroup *padgrp = &community->gpps[i];
|
||||
const struct intel_padgroup *padgrp;
|
||||
|
||||
for_each_intel_community_pad_group(community, padgrp) {
|
||||
if (pin >= padgrp->base && pin < padgrp->base + padgrp->size)
|
||||
return padgrp;
|
||||
}
|
||||
@ -161,7 +182,7 @@ static void __iomem *intel_get_padcfg(struct intel_pinctrl *pctrl,
|
||||
return community->pad_regs + reg + padno * nregs * 4;
|
||||
}
|
||||
|
||||
static bool intel_pad_owned_by_host(struct intel_pinctrl *pctrl, unsigned int pin)
|
||||
static bool intel_pad_owned_by_host(const struct intel_pinctrl *pctrl, unsigned int pin)
|
||||
{
|
||||
const struct intel_community *community;
|
||||
const struct intel_padgroup *padgrp;
|
||||
@ -186,7 +207,7 @@ static bool intel_pad_owned_by_host(struct intel_pinctrl *pctrl, unsigned int pi
|
||||
return !(readl(padown) & PADOWN_MASK(gpp_offset));
|
||||
}
|
||||
|
||||
static bool intel_pad_acpi_mode(struct intel_pinctrl *pctrl, unsigned int pin)
|
||||
static bool intel_pad_acpi_mode(const struct intel_pinctrl *pctrl, unsigned int pin)
|
||||
{
|
||||
const struct intel_community *community;
|
||||
const struct intel_padgroup *padgrp;
|
||||
@ -212,7 +233,6 @@ static bool intel_pad_acpi_mode(struct intel_pinctrl *pctrl, unsigned int pin)
|
||||
|
||||
/**
|
||||
* enum - Locking variants of the pad configuration
|
||||
*
|
||||
* @PAD_UNLOCKED: pad is fully controlled by the configuration registers
|
||||
* @PAD_LOCKED: pad configuration registers, except TX state, are locked
|
||||
* @PAD_LOCKED_TX: pad configuration TX state is locked
|
||||
@ -229,9 +249,9 @@ enum {
|
||||
PAD_LOCKED_FULL = PAD_LOCKED | PAD_LOCKED_TX,
|
||||
};
|
||||
|
||||
static int intel_pad_locked(struct intel_pinctrl *pctrl, unsigned int pin)
|
||||
static int intel_pad_locked(const struct intel_pinctrl *pctrl, unsigned int pin)
|
||||
{
|
||||
struct intel_community *community;
|
||||
const struct intel_community *community;
|
||||
const struct intel_padgroup *padgrp;
|
||||
unsigned int offset, gpp_offset;
|
||||
u32 value;
|
||||
@ -267,19 +287,19 @@ static int intel_pad_locked(struct intel_pinctrl *pctrl, unsigned int pin)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool intel_pad_is_unlocked(struct intel_pinctrl *pctrl, unsigned int pin)
|
||||
static bool intel_pad_is_unlocked(const struct intel_pinctrl *pctrl, unsigned int pin)
|
||||
{
|
||||
return (intel_pad_locked(pctrl, pin) & PAD_LOCKED) == PAD_UNLOCKED;
|
||||
}
|
||||
|
||||
static bool intel_pad_usable(struct intel_pinctrl *pctrl, unsigned int pin)
|
||||
static bool intel_pad_usable(const struct intel_pinctrl *pctrl, unsigned int pin)
|
||||
{
|
||||
return intel_pad_owned_by_host(pctrl, pin) && intel_pad_is_unlocked(pctrl, pin);
|
||||
}
|
||||
|
||||
int intel_get_groups_count(struct pinctrl_dev *pctldev)
|
||||
{
|
||||
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
const struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
return pctrl->soc->ngroups;
|
||||
}
|
||||
@ -287,7 +307,7 @@ EXPORT_SYMBOL_NS_GPL(intel_get_groups_count, PINCTRL_INTEL);
|
||||
|
||||
const char *intel_get_group_name(struct pinctrl_dev *pctldev, unsigned int group)
|
||||
{
|
||||
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
const struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
return pctrl->soc->groups[group].grp.name;
|
||||
}
|
||||
@ -296,7 +316,7 @@ EXPORT_SYMBOL_NS_GPL(intel_get_group_name, PINCTRL_INTEL);
|
||||
int intel_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);
|
||||
const struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
*pins = pctrl->soc->groups[group].grp.pins;
|
||||
*npins = pctrl->soc->groups[group].grp.npins;
|
||||
@ -364,7 +384,7 @@ static const struct pinctrl_ops intel_pinctrl_ops = {
|
||||
|
||||
int intel_get_functions_count(struct pinctrl_dev *pctldev)
|
||||
{
|
||||
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
const struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
return pctrl->soc->nfunctions;
|
||||
}
|
||||
@ -372,7 +392,7 @@ EXPORT_SYMBOL_NS_GPL(intel_get_functions_count, PINCTRL_INTEL);
|
||||
|
||||
const char *intel_get_function_name(struct pinctrl_dev *pctldev, unsigned int function)
|
||||
{
|
||||
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
const struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
return pctrl->soc->functions[function].func.name;
|
||||
}
|
||||
@ -381,7 +401,7 @@ EXPORT_SYMBOL_NS_GPL(intel_get_function_name, PINCTRL_INTEL);
|
||||
int intel_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);
|
||||
const struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
*groups = pctrl->soc->functions[function].func.groups;
|
||||
*ngroups = pctrl->soc->functions[function].func.ngroups;
|
||||
@ -429,19 +449,49 @@ static int intel_pinmux_set_mux(struct pinctrl_dev *pctldev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __intel_gpio_set_direction(void __iomem *padcfg0, bool input)
|
||||
{
|
||||
u32 value;
|
||||
/**
|
||||
* enum - Possible pad physical connections
|
||||
* @PAD_CONNECT_NONE: pad is fully disconnected
|
||||
* @PAD_CONNECT_INPUT: pad is in input only mode
|
||||
* @PAD_CONNECT_OUTPUT: pad is in output only mode
|
||||
* @PAD_CONNECT_FULL: pad is fully connected
|
||||
*/
|
||||
enum {
|
||||
PAD_CONNECT_NONE = 0,
|
||||
PAD_CONNECT_INPUT = 1,
|
||||
PAD_CONNECT_OUTPUT = 2,
|
||||
PAD_CONNECT_FULL = PAD_CONNECT_INPUT | PAD_CONNECT_OUTPUT,
|
||||
};
|
||||
|
||||
value = readl(padcfg0);
|
||||
if (input) {
|
||||
static int __intel_gpio_get_direction(u32 value)
|
||||
{
|
||||
switch ((value & PADCFG0_GPIODIS_MASK) >> PADCFG0_GPIODIS_SHIFT) {
|
||||
case PADCFG0_GPIODIS_FULL:
|
||||
return PAD_CONNECT_NONE;
|
||||
case PADCFG0_GPIODIS_OUTPUT:
|
||||
return PAD_CONNECT_INPUT;
|
||||
case PADCFG0_GPIODIS_INPUT:
|
||||
return PAD_CONNECT_OUTPUT;
|
||||
case PADCFG0_GPIODIS_NONE:
|
||||
return PAD_CONNECT_FULL;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
};
|
||||
}
|
||||
|
||||
static u32 __intel_gpio_set_direction(u32 value, bool input, bool output)
|
||||
{
|
||||
if (input)
|
||||
value &= ~PADCFG0_GPIORXDIS;
|
||||
value |= PADCFG0_GPIOTXDIS;
|
||||
} else {
|
||||
value &= ~PADCFG0_GPIOTXDIS;
|
||||
else
|
||||
value |= PADCFG0_GPIORXDIS;
|
||||
}
|
||||
writel(value, padcfg0);
|
||||
|
||||
if (output)
|
||||
value &= ~PADCFG0_GPIOTXDIS;
|
||||
else
|
||||
value |= PADCFG0_GPIOTXDIS;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static int __intel_gpio_get_gpio_mode(u32 value)
|
||||
@ -465,8 +515,7 @@ static void intel_gpio_set_gpio_mode(void __iomem *padcfg0)
|
||||
value |= PADCFG0_PMODE_GPIO;
|
||||
|
||||
/* Disable TX buffer and enable RX (this will be input) */
|
||||
value &= ~PADCFG0_GPIORXDIS;
|
||||
value |= PADCFG0_GPIOTXDIS;
|
||||
value = __intel_gpio_set_direction(value, true, false);
|
||||
|
||||
/* Disable SCI/SMI/NMI generation */
|
||||
value &= ~(PADCFG0_GPIROUTIOXAPIC | PADCFG0_GPIROUTSCI);
|
||||
@ -512,12 +561,18 @@ static int intel_gpio_set_direction(struct pinctrl_dev *pctldev,
|
||||
{
|
||||
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
void __iomem *padcfg0;
|
||||
u32 value;
|
||||
|
||||
padcfg0 = intel_get_padcfg(pctrl, pin, PADCFG0);
|
||||
|
||||
guard(raw_spinlock_irqsave)(&pctrl->lock);
|
||||
|
||||
__intel_gpio_set_direction(padcfg0, input);
|
||||
value = readl(padcfg0);
|
||||
if (input)
|
||||
value = __intel_gpio_set_direction(value, true, false);
|
||||
else
|
||||
value = __intel_gpio_set_direction(value, false, true);
|
||||
writel(value, padcfg0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -612,6 +667,23 @@ static int intel_config_get_pull(struct intel_pinctrl *pctrl, unsigned int pin,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int intel_config_get_high_impedance(struct intel_pinctrl *pctrl, unsigned int pin,
|
||||
enum pin_config_param param, u32 *arg)
|
||||
{
|
||||
void __iomem *padcfg0;
|
||||
u32 value;
|
||||
|
||||
padcfg0 = intel_get_padcfg(pctrl, pin, PADCFG0);
|
||||
|
||||
scoped_guard(raw_spinlock_irqsave, &pctrl->lock)
|
||||
value = readl(padcfg0);
|
||||
|
||||
if (__intel_gpio_get_direction(value) != PAD_CONNECT_NONE)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int intel_config_get_debounce(struct intel_pinctrl *pctrl, unsigned int pin,
|
||||
enum pin_config_param param, u32 *arg)
|
||||
{
|
||||
@ -655,6 +727,12 @@ static int intel_config_get(struct pinctrl_dev *pctldev, unsigned int pin,
|
||||
return ret;
|
||||
break;
|
||||
|
||||
case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
|
||||
ret = intel_config_get_high_impedance(pctrl, pin, param, &arg);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
|
||||
case PIN_CONFIG_INPUT_DEBOUNCE:
|
||||
ret = intel_config_get_debounce(pctrl, pin, param, &arg);
|
||||
if (ret)
|
||||
@ -753,11 +831,34 @@ static int intel_config_set_pull(struct intel_pinctrl *pctrl, unsigned int pin,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void intel_gpio_set_high_impedance(struct intel_pinctrl *pctrl, unsigned int pin)
|
||||
{
|
||||
void __iomem *padcfg0;
|
||||
u32 value;
|
||||
|
||||
padcfg0 = intel_get_padcfg(pctrl, pin, PADCFG0);
|
||||
|
||||
guard(raw_spinlock_irqsave)(&pctrl->lock);
|
||||
|
||||
value = readl(padcfg0);
|
||||
value = __intel_gpio_set_direction(value, false, false);
|
||||
writel(value, padcfg0);
|
||||
}
|
||||
|
||||
static int intel_config_set_debounce(struct intel_pinctrl *pctrl,
|
||||
unsigned int pin, unsigned int debounce)
|
||||
{
|
||||
void __iomem *padcfg0, *padcfg2;
|
||||
u32 value0, value2;
|
||||
unsigned long v;
|
||||
|
||||
if (debounce) {
|
||||
v = order_base_2(debounce * NSEC_PER_USEC / DEBOUNCE_PERIOD_NSEC);
|
||||
if (v < 3 || v > 15)
|
||||
return -EINVAL;
|
||||
} else {
|
||||
v = 0;
|
||||
}
|
||||
|
||||
padcfg2 = intel_get_padcfg(pctrl, pin, PADCFG2);
|
||||
if (!padcfg2)
|
||||
@ -770,21 +871,15 @@ static int intel_config_set_debounce(struct intel_pinctrl *pctrl,
|
||||
value0 = readl(padcfg0);
|
||||
value2 = readl(padcfg2);
|
||||
|
||||
/* Disable glitch filter and debouncer */
|
||||
value0 &= ~PADCFG0_PREGFRXSEL;
|
||||
value2 &= ~(PADCFG2_DEBEN | PADCFG2_DEBOUNCE_MASK);
|
||||
|
||||
if (debounce) {
|
||||
unsigned long v;
|
||||
|
||||
v = order_base_2(debounce * NSEC_PER_USEC / DEBOUNCE_PERIOD_NSEC);
|
||||
if (v < 3 || v > 15)
|
||||
return -EINVAL;
|
||||
|
||||
value2 = (value2 & ~PADCFG2_DEBOUNCE_MASK) | (v << PADCFG2_DEBOUNCE_SHIFT);
|
||||
if (v) {
|
||||
/* Enable glitch filter and debouncer */
|
||||
value0 |= PADCFG0_PREGFRXSEL;
|
||||
value2 |= v << PADCFG2_DEBOUNCE_SHIFT;
|
||||
value2 |= PADCFG2_DEBEN;
|
||||
} else {
|
||||
/* Disable glitch filter and debouncer */
|
||||
value0 &= ~PADCFG0_PREGFRXSEL;
|
||||
value2 &= ~PADCFG2_DEBEN;
|
||||
}
|
||||
|
||||
writel(value0, padcfg0);
|
||||
@ -812,6 +907,10 @@ static int intel_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
|
||||
return ret;
|
||||
break;
|
||||
|
||||
case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
|
||||
intel_gpio_set_high_impedance(pctrl, pin);
|
||||
break;
|
||||
|
||||
case PIN_CONFIG_INPUT_DEBOUNCE:
|
||||
ret = intel_config_set_debounce(pctrl, pin,
|
||||
pinconf_to_config_argument(configs[i]));
|
||||
@ -854,34 +953,21 @@ static const struct pinctrl_desc intel_pinctrl_desc = {
|
||||
* Return: a pin number and pointers to the community and pad group, which
|
||||
* the pin belongs to, or negative error code if translation can't be done.
|
||||
*/
|
||||
static int intel_gpio_to_pin(struct intel_pinctrl *pctrl, unsigned int offset,
|
||||
static int intel_gpio_to_pin(const struct intel_pinctrl *pctrl, unsigned int offset,
|
||||
const struct intel_community **community,
|
||||
const struct intel_padgroup **padgrp)
|
||||
{
|
||||
int i;
|
||||
const struct intel_community *comm;
|
||||
const struct intel_padgroup *grp;
|
||||
|
||||
for (i = 0; i < pctrl->ncommunities; i++) {
|
||||
const struct intel_community *comm = &pctrl->communities[i];
|
||||
int j;
|
||||
for_each_intel_gpio_group(pctrl, comm, grp) {
|
||||
if (offset >= grp->gpio_base && offset < grp->gpio_base + grp->size) {
|
||||
if (community)
|
||||
*community = comm;
|
||||
if (padgrp)
|
||||
*padgrp = grp;
|
||||
|
||||
for (j = 0; j < comm->ngpps; j++) {
|
||||
const struct intel_padgroup *pgrp = &comm->gpps[j];
|
||||
|
||||
if (pgrp->gpio_base == INTEL_GPIO_BASE_NOMAP)
|
||||
continue;
|
||||
|
||||
if (offset >= pgrp->gpio_base &&
|
||||
offset < pgrp->gpio_base + pgrp->size) {
|
||||
int pin;
|
||||
|
||||
pin = pgrp->base + offset - pgrp->gpio_base;
|
||||
if (community)
|
||||
*community = comm;
|
||||
if (padgrp)
|
||||
*padgrp = pgrp;
|
||||
|
||||
return pin;
|
||||
}
|
||||
return grp->base + offset - grp->gpio_base;
|
||||
}
|
||||
}
|
||||
|
||||
@ -897,7 +983,7 @@ static int intel_gpio_to_pin(struct intel_pinctrl *pctrl, unsigned int offset,
|
||||
*
|
||||
* Return: a GPIO offset, or negative error code if translation can't be done.
|
||||
*/
|
||||
static int intel_pin_to_gpio(struct intel_pinctrl *pctrl, int pin)
|
||||
static int intel_pin_to_gpio(const struct intel_pinctrl *pctrl, int pin)
|
||||
{
|
||||
const struct intel_community *community;
|
||||
const struct intel_padgroup *padgrp;
|
||||
@ -929,7 +1015,7 @@ static int intel_gpio_get(struct gpio_chip *chip, unsigned int offset)
|
||||
return -EINVAL;
|
||||
|
||||
padcfg0 = readl(reg);
|
||||
if (!(padcfg0 & PADCFG0_GPIOTXDIS))
|
||||
if (__intel_gpio_get_direction(padcfg0) & PAD_CONNECT_OUTPUT)
|
||||
return !!(padcfg0 & PADCFG0_GPIOTXSTATE);
|
||||
|
||||
return !!(padcfg0 & PADCFG0_GPIORXSTATE);
|
||||
@ -982,10 +1068,10 @@ static int intel_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
|
||||
if (padcfg0 & PADCFG0_PMODE_MASK)
|
||||
return -EINVAL;
|
||||
|
||||
if (padcfg0 & PADCFG0_GPIOTXDIS)
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
if (__intel_gpio_get_direction(padcfg0) & PAD_CONNECT_OUTPUT)
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static int intel_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
|
||||
@ -1171,15 +1257,16 @@ static const struct irq_chip intel_gpio_irq_chip = {
|
||||
GPIOCHIP_IRQ_RESOURCE_HELPERS,
|
||||
};
|
||||
|
||||
static int intel_gpio_community_irq_handler(struct intel_pinctrl *pctrl,
|
||||
const struct intel_community *community)
|
||||
static irqreturn_t intel_gpio_irq(int irq, void *data)
|
||||
{
|
||||
struct gpio_chip *gc = &pctrl->chip;
|
||||
unsigned int gpp;
|
||||
const struct intel_community *community;
|
||||
const struct intel_padgroup *padgrp;
|
||||
struct intel_pinctrl *pctrl = data;
|
||||
int ret = 0;
|
||||
|
||||
for (gpp = 0; gpp < community->ngpps; gpp++) {
|
||||
const struct intel_padgroup *padgrp = &community->gpps[gpp];
|
||||
/* Need to check all communities for pending interrupts */
|
||||
for_each_intel_pad_group(pctrl, community, padgrp) {
|
||||
struct gpio_chip *gc = &pctrl->chip;
|
||||
unsigned long pending, enabled;
|
||||
unsigned int gpp, gpp_offset;
|
||||
void __iomem *reg, *is;
|
||||
@ -1203,36 +1290,17 @@ static int intel_gpio_community_irq_handler(struct intel_pinctrl *pctrl,
|
||||
ret += pending ? 1 : 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static irqreturn_t intel_gpio_irq(int irq, void *data)
|
||||
{
|
||||
const struct intel_community *community;
|
||||
struct intel_pinctrl *pctrl = data;
|
||||
unsigned int i;
|
||||
int ret = 0;
|
||||
|
||||
/* Need to check all communities for pending interrupts */
|
||||
for (i = 0; i < pctrl->ncommunities; i++) {
|
||||
community = &pctrl->communities[i];
|
||||
ret += intel_gpio_community_irq_handler(pctrl, community);
|
||||
}
|
||||
|
||||
return IRQ_RETVAL(ret);
|
||||
}
|
||||
|
||||
static void intel_gpio_irq_init(struct intel_pinctrl *pctrl)
|
||||
{
|
||||
int i;
|
||||
const struct intel_community *community;
|
||||
|
||||
for (i = 0; i < pctrl->ncommunities; i++) {
|
||||
const struct intel_community *community;
|
||||
for_each_intel_pin_community(pctrl, community) {
|
||||
void __iomem *reg, *is;
|
||||
unsigned int gpp;
|
||||
|
||||
community = &pctrl->communities[i];
|
||||
|
||||
for (gpp = 0; gpp < community->ngpps; gpp++) {
|
||||
reg = community->regs + community->ie_offset + gpp * 4;
|
||||
is = community->regs + community->is_offset + gpp * 4;
|
||||
@ -1257,36 +1325,17 @@ static int intel_gpio_irq_init_hw(struct gpio_chip *gc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int intel_gpio_add_community_ranges(struct intel_pinctrl *pctrl,
|
||||
const struct intel_community *community)
|
||||
{
|
||||
int ret = 0, i;
|
||||
|
||||
for (i = 0; i < community->ngpps; i++) {
|
||||
const struct intel_padgroup *gpp = &community->gpps[i];
|
||||
|
||||
if (gpp->gpio_base == INTEL_GPIO_BASE_NOMAP)
|
||||
continue;
|
||||
|
||||
ret = gpiochip_add_pin_range(&pctrl->chip, dev_name(pctrl->dev),
|
||||
gpp->gpio_base, gpp->base,
|
||||
gpp->size);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int intel_gpio_add_pin_ranges(struct gpio_chip *gc)
|
||||
{
|
||||
struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
|
||||
int ret, i;
|
||||
const struct intel_community *community;
|
||||
const struct intel_padgroup *grp;
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < pctrl->ncommunities; i++) {
|
||||
struct intel_community *community = &pctrl->communities[i];
|
||||
|
||||
ret = intel_gpio_add_community_ranges(pctrl, community);
|
||||
for_each_intel_gpio_group(pctrl, community, grp) {
|
||||
ret = gpiochip_add_pin_range(&pctrl->chip, dev_name(pctrl->dev),
|
||||
grp->gpio_base, grp->base,
|
||||
grp->size);
|
||||
if (ret) {
|
||||
dev_err(pctrl->dev, "failed to add GPIO pin range\n");
|
||||
return ret;
|
||||
@ -1299,20 +1348,12 @@ static int intel_gpio_add_pin_ranges(struct gpio_chip *gc)
|
||||
static unsigned int intel_gpio_ngpio(const struct intel_pinctrl *pctrl)
|
||||
{
|
||||
const struct intel_community *community;
|
||||
const struct intel_padgroup *grp;
|
||||
unsigned int ngpio = 0;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < pctrl->ncommunities; i++) {
|
||||
community = &pctrl->communities[i];
|
||||
for (j = 0; j < community->ngpps; j++) {
|
||||
const struct intel_padgroup *gpp = &community->gpps[j];
|
||||
|
||||
if (gpp->gpio_base == INTEL_GPIO_BASE_NOMAP)
|
||||
continue;
|
||||
|
||||
if (gpp->gpio_base + gpp->size > ngpio)
|
||||
ngpio = gpp->gpio_base + gpp->size;
|
||||
}
|
||||
for_each_intel_gpio_group(pctrl, community, grp) {
|
||||
if (grp->gpio_base + grp->size > ngpio)
|
||||
ngpio = grp->gpio_base + grp->size;
|
||||
}
|
||||
|
||||
return ngpio;
|
||||
@ -1682,7 +1723,8 @@ EXPORT_SYMBOL_NS_GPL(intel_pinctrl_get_soc_data, PINCTRL_INTEL);
|
||||
|
||||
static bool __intel_gpio_is_direct_irq(u32 value)
|
||||
{
|
||||
return (value & PADCFG0_GPIROUTIOXAPIC) && (value & PADCFG0_GPIOTXDIS) &&
|
||||
return (value & PADCFG0_GPIROUTIOXAPIC) &&
|
||||
(__intel_gpio_get_direction(value) == PAD_CONNECT_INPUT) &&
|
||||
(__intel_gpio_get_gpio_mode(value) == PADCFG0_PMODE_GPIO);
|
||||
}
|
||||
|
||||
|
@ -264,7 +264,8 @@ int intel_pinctrl_probe_by_uid(struct platform_device *pdev);
|
||||
|
||||
extern const struct dev_pm_ops intel_pinctrl_pm_ops;
|
||||
|
||||
struct intel_community *intel_get_community(struct intel_pinctrl *pctrl, unsigned int pin);
|
||||
const struct intel_community *intel_get_community(const 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);
|
||||
|
@ -211,7 +211,7 @@ static void __iomem *lp_gpio_reg(struct gpio_chip *chip, unsigned int offset,
|
||||
int reg)
|
||||
{
|
||||
struct intel_pinctrl *lg = gpiochip_get_data(chip);
|
||||
struct intel_community *comm;
|
||||
const struct intel_community *comm;
|
||||
int reg_offset;
|
||||
|
||||
comm = intel_get_community(lg, offset);
|
||||
|
Loading…
Reference in New Issue
Block a user