// SPDX-License-Identifier: GPL-2.0-only /* * linux/arch/arm/mach-pxa/mfp-pxa2xx.c * * PXA2xx pin mux configuration support * * The GPIOs on PXA2xx can be configured as one of many alternate * functions, this is by concept samilar to the MFP configuration * on PXA3xx, what's more important, the low power pin state and * wakeup detection are also supported by the same framework.
*/ #include <linux/gpio.h> #include <linux/gpio-pxa.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/io.h> #include <linux/syscore_ops.h> #include <linux/soc/pxa/cpu.h>
/* alternate function and direction at low power mode */ switch (c & MFP_LPM_STATE_MASK) { case MFP_LPM_DRIVE_HIGH:
PGSR(bank) |= mask;
is_out = 1; break; case MFP_LPM_DRIVE_LOW:
PGSR(bank) &= ~mask;
is_out = 1; break; case MFP_LPM_INPUT: case MFP_LPM_DEFAULT: break; default: /* warning and fall through, treat as MFP_LPM_DEFAULT */
pr_warn("%s: GPIO%d: unsupported low power mode\n",
__func__, gpio); break;
}
/* give early warning if MFP_LPM_CAN_WAKEUP is set on the * configurations of those pins not able to wakeup
*/ if ((c & MFP_LPM_CAN_WAKEUP) && !gpio_desc[gpio].can_wakeup) {
pr_warn("%s: GPIO%d unable to wakeup\n", __func__, gpio); return -EINVAL;
}
if ((c & MFP_LPM_CAN_WAKEUP) && is_out) {
pr_warn("%s: output GPIO%d unable to wakeup\n", __func__, gpio); return -EINVAL;
}
return 0;
}
staticinlineint __mfp_validate(int mfp)
{ int gpio = mfp_to_gpio(mfp);
if ((mfp > MFP_PIN_GPIO127) || !gpio_desc[gpio].valid) {
pr_warn("%s: GPIO%d is invalid pin\n", __func__, gpio); return -1;
}
return gpio;
}
void pxa2xx_mfp_config(unsignedlong *mfp_cfgs, int num)
{ unsignedlong flags; unsignedlong *c; int i, gpio;
for (i = 0, c = mfp_cfgs; i < num; i++, c++) {
gpio = __mfp_validate(MFP_PIN(*c)); if (gpio < 0) continue;
#ifdef CONFIG_PXA25x staticvoid __init pxa25x_mfp_init(void)
{ int i;
/* running before pxa_gpio_probe() */
pxa_last_gpio = 84; for (i = 0; i <= pxa_last_gpio; i++)
gpio_desc[i].valid = 1;
for (i = 0; i <= 15; i++) {
gpio_desc[i].can_wakeup = 1;
gpio_desc[i].mask = GPIO_bit(i);
}
/* PXA26x has additional 4 GPIOs (86/87/88/89) which has the * direction bit inverted in GPDR2. See PXA26x DM 4.1.1.
*/ for (i = 86; i <= pxa_last_gpio; i++)
gpio_desc[i].dir_inverted = 1;
} #else staticinlinevoid pxa25x_mfp_init(void) {} #endif/* CONFIG_PXA25x */
staticvoid __init pxa27x_mfp_init(void)
{ int i, gpio;
pxa_last_gpio = 120; /* running before pxa_gpio_probe() */ for (i = 0; i <= pxa_last_gpio; i++) { /* skip GPIO2, 5, 6, 7, 8, they are not * valid pins allow configuration
*/ if (i == 2 || i == 5 || i == 6 || i == 7 || i == 8) continue;
gpio_desc[i].valid = 1;
}
/* Keypad GPIOs */ for (i = 0; i < ARRAY_SIZE(pxa27x_pkwr_gpio); i++) {
gpio = pxa27x_pkwr_gpio[i];
gpio_desc[gpio].can_wakeup = 1;
gpio_desc[gpio].keypad_gpio = 1;
gpio_desc[gpio].mask = 1 << i;
}
/* Overwrite GPIO13 as a PWER wakeup source */ for (i = 0; i <= 15; i++) { /* skip GPIO2, 5, 6, 7, 8 */ if (GPIO_bit(i) & 0x1e4) continue;
/* set corresponding PGSR bit of those marked MFP_LPM_KEEP_OUTPUT */ for (i = 0; i < pxa_last_gpio; i++) { if ((gpio_desc[i].config & MFP_LPM_KEEP_OUTPUT) &&
(GPDR(i) & GPIO_bit(i))) { if (GPLR(i) & GPIO_bit(i))
PGSR(gpio_to_bank(i)) |= GPIO_bit(i); else
PGSR(gpio_to_bank(i)) &= ~GPIO_bit(i);
}
}
for (i = 0; i <= gpio_to_bank(pxa_last_gpio); i++) {
saved_gafr[0][i] = GAFR_L(i);
saved_gafr[1][i] = GAFR_U(i);
saved_gpdr[i] = GPDR(i * 32);
saved_gplr[i] = GPLR(i * 32);
saved_pgsr[i] = PGSR(i);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.