<commit_before>/*
 *  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.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 2 as
 *  published by the Free Software Foundation.
 */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sysdev.h>

#include <asm/arch/hardware.h>
#include <asm/arch/pxa-regs.h>
#include <asm/arch/pxa2xx-regs.h>
#include <asm/arch/mfp-pxa2xx.h>

#include "generic.h"

#define PGSR(x)		__REG2(0x40F00020, ((x) & 0x60) >> 3)

#define PWER_WE35	(1 << 24)

struct gpio_desc {
	unsigned	valid		: 1;
	unsigned	can_wakeup	: 1;
	unsigned	keypad_gpio	: 1;
	unsigned int	mask; /* bit mask in PWER or PKWR */
	unsigned long	config;
};

static struct gpio_desc gpio_desc[MFP_PIN_GPIO127 + 1];

static int __mfp_config_gpio(unsigned gpio, unsigned long c)
{
	unsigned long gafr, mask = GPIO_bit(gpio);
	int fn;

	fn = MFP_AF(c);
	if (fn > 3)
		return -EINVAL;

	/* alternate function and direction */
	gafr = GAFR(gpio) & ~(0x3 << ((gpio & 0xf) * 2));
	GAFR(gpio) = gafr |  (fn  << ((gpio & 0xf) * 2));

	if (c & MFP_DIR_OUT)
		GPDR(gpio) |= mask;
	else
		GPDR(gpio) &= ~mask;

	/* low power state */
	switch (c & MFP_LPM_STATE_MASK) {
	case MFP_LPM_DRIVE_HIGH:
		PGSR(gpio) |= mask;
		break;
	case MFP_LPM_DRIVE_LOW:
		PGSR(gpio) &= ~mask;
		break;
	case MFP_LPM_INPUT:
		break;
	default:
		pr_warning("%s: invalid low power state for GPIO%d\n",
				__func__, gpio);
		return -EINVAL;
	}

	/* 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_warning("%s: GPIO%d unable to wakeup\n",
				__func__, gpio);
		return -EINVAL;
	}

	if ((c & MFP_LPM_CAN_WAKEUP) && (c & MFP_DIR_OUT)) {
		pr_warning("%s: output GPIO%d unable to wakeup\n",
				__func__, gpio);
		return -EINVAL;
	}

	return 0;
}

void pxa2xx_mfp_config(unsigned long *mfp_cfgs, int num)
{
	unsigned long flags;
	unsigned long *c;
	int i, gpio;

	for (i = 0, c = mfp_cfgs; i < num; i++, c++) {

		gpio = mfp_to_gpio(MFP_PIN(*c));

		if (!gpio_desc[gpio].valid) {
			pr_warning("%s: GPIO%d is invalid pin\n",
				__func__, gpio);
			continue;
		}

		local_irq_save(flags);

		gpio_desc[gpio].config = *c;
		__mfp_config_gpio(gpio, *c);

		local_irq_restore(flags);
	}
}

int gpio_set_wake(unsigned int gpio, unsigned int on)
{
	struct gpio_desc *d;
	unsigned long c;

	if (gpio > mfp_to_gpio(MFP_PIN_GPIO127))
		return -EINVAL;
<commit_msg>[ARM] pxa: introduce dedicated __mfp_validate() to check PXA2xx MFP<commit_after>/*
 *  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.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 2 as
 *  published by the Free Software Foundation.
 */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sysdev.h>

#include <asm/arch/hardware.h>
#include <asm/arch/pxa-regs.h>
#include <asm/arch/pxa2xx-regs.h>
#include <asm/arch/mfp-pxa2xx.h>

#include "generic.h"

#define PGSR(x)		__REG2(0x40F00020, ((x) & 0x60) >> 3)

#define PWER_WE35	(1 << 24)

struct gpio_desc {
	unsigned	valid		: 1;
	unsigned	can_wakeup	: 1;
	unsigned	keypad_gpio	: 1;
	unsigned int	mask; /* bit mask in PWER or PKWR */
	unsigned long	config;
};

static struct gpio_desc gpio_desc[MFP_PIN_GPIO127 + 1];

static int __mfp_config_gpio(unsigned gpio, unsigned long c)
{
	unsigned long gafr, mask = GPIO_bit(gpio);
	int fn;

	fn = MFP_AF(c);
	if (fn > 3)
		return -EINVAL;

	/* alternate function and direction */
	gafr = GAFR(gpio) & ~(0x3 << ((gpio & 0xf) * 2));
	GAFR(gpio) = gafr |  (fn  << ((gpio & 0xf) * 2));

	if (c & MFP_DIR_OUT)
		GPDR(gpio) |= mask;
	else
		GPDR(gpio) &= ~mask;

	/* low power state */
	switch (c & MFP_LPM_STATE_MASK) {
	case MFP_LPM_DRIVE_HIGH:
		PGSR(gpio) |= mask;
		break;
	case MFP_LPM_DRIVE_LOW:
		PGSR(gpio) &= ~mask;
		break;
	case MFP_LPM_INPUT:
		break;
	default:
		pr_warning("%s: invalid low power state for GPIO%d\n",
				__func__, gpio);
		return -EINVAL;
	}

	/* 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_warning("%s: GPIO%d unable to wakeup\n",
				__func__, gpio);
		return -EINVAL;
	}

	if ((c & MFP_LPM_CAN_WAKEUP) && (c & MFP_DIR_OUT)) {
		pr_warning("%s: output GPIO%d unable to wakeup\n",
				__func__, gpio);
		return -EINVAL;
	}

	return 0;
}

static inline int __mfp_validate(int mfp)
{
	int gpio = mfp_to_gpio(mfp);

	if ((mfp > MFP_PIN_GPIO127) || !gpio_desc[gpio].valid) {
		pr_warning("%s: GPIO%d is invalid pin\n", __func__, gpio);
		return -1;
	}

	return gpio;
}

void pxa2xx_mfp_config(unsigned long *mfp_cfgs, int num)
{
	unsigned long flags;
	unsigned long *c;
	int i, gpio;

	for (i = 0, c = mfp_cfgs; i < num; i++, c++) {

		gpio = __mfp_validate(MFP_PIN(*c));
		if (gpio < 0)
			continue;

		local_irq_save(flags);

		gpio_desc[gpio].config = *c;
		__mfp_config_gpio(gpio, *c);

		local_irq_restore(flags);
	}
}

int gpio_set_wake(unsigned int gpio, unsigned int on)
{
	struct gpio_desc *d;
	unsigned long c;

	if (gpio > mfp_to_gpio(MFP_PIN_GPIO127))
		return -EINVAL;

{'fraction_non_alphanumeric': 0.12920592193808883, 'fraction_numerical': 0.016150740242261104, 'mean_word_length': 3.7712680577849116, 'pattern_counts': {'":': 0, '<': 34, '<?xml version=': 0, '>': 28, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3926147', 'n_tokens_mistral': 2564, 'n_tokens_neox': 2391, 'n_words': 661}