コード例 #1
0
static void __nmk_gpio_set_mode_safe(struct nmk_gpio_chip *nmk_chip,
				     unsigned offset, int gpio_mode,
				     bool glitch)
{
	u32 rwimsc = nmk_chip->rwimsc;
	u32 fwimsc = nmk_chip->fwimsc;

	if (glitch && nmk_chip->set_ioforce) {
		u32 bit = BIT(offset);

		/* Prevent spurious wakeups */
		writel(rwimsc & ~bit, nmk_chip->addr + NMK_GPIO_RWIMSC);
		writel(fwimsc & ~bit, nmk_chip->addr + NMK_GPIO_FWIMSC);

		nmk_chip->set_ioforce(true);
	}

	__nmk_gpio_set_mode(nmk_chip, offset, gpio_mode);

	if (glitch && nmk_chip->set_ioforce) {
		nmk_chip->set_ioforce(false);

		writel(rwimsc, nmk_chip->addr + NMK_GPIO_RWIMSC);
		writel(fwimsc, nmk_chip->addr + NMK_GPIO_FWIMSC);
	}
}
コード例 #2
0
int nmk_gpio_request_enable(struct pinctrl_dev *pctldev,
			    struct pinctrl_gpio_range *range,
			    unsigned offset)
{
	struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
	struct nmk_gpio_chip *nmk_chip;
	struct gpio_chip *chip;
	unsigned bit;

	if (!range) {
		dev_err(npct->dev, "invalid range\n");
		return -EINVAL;
	}
	if (!range->gc) {
		dev_err(npct->dev, "missing GPIO chip in range\n");
		return -EINVAL;
	}
	chip = range->gc;
	nmk_chip = container_of(chip, struct nmk_gpio_chip, chip);

	dev_dbg(npct->dev, "enable pin %u as GPIO\n", offset);

	clk_enable(nmk_chip->clk);
	bit = offset % NMK_GPIO_PER_CHIP;
	/* There is no glitch when converting any pin to GPIO */
	__nmk_gpio_set_mode(nmk_chip, bit, NMK_GPIO_ALT_GPIO);
	clk_disable(nmk_chip->clk);

	return 0;
}
コード例 #3
0
/**
 * nmk_gpio_set_mode() - set the mux mode of a gpio pin
 * @gpio: pin number
 * @gpio_mode: one of NMK_GPIO_ALT_GPIO, NMK_GPIO_ALT_A,
 *	       NMK_GPIO_ALT_B, and NMK_GPIO_ALT_C
 *
 * Sets the mode of the specified pin to one of the alternate functions or
 * plain GPIO.
 */
int nmk_gpio_set_mode(int gpio, int gpio_mode)
{
	struct nmk_gpio_chip *nmk_chip;
	unsigned long flags;

	nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
	if (!nmk_chip)
		return -EINVAL;

	spin_lock_irqsave(&nmk_chip->lock, flags);
	__nmk_gpio_set_mode(nmk_chip, gpio - nmk_chip->chip.base, gpio_mode);
	spin_unlock_irqrestore(&nmk_chip->lock, flags);

	return 0;
}
コード例 #4
0
/**
 * nmk_gpio_set_mode() - set the mux mode of a gpio pin
 * @gpio: pin number
 * @gpio_mode: one of NMK_GPIO_ALT_GPIO, NMK_GPIO_ALT_A,
 *	       NMK_GPIO_ALT_B, and NMK_GPIO_ALT_C
 *
 * Sets the mode of the specified pin to one of the alternate functions or
 * plain GPIO.
 */
int nmk_gpio_set_mode(int gpio, int gpio_mode)
{
	struct nmk_gpio_chip *nmk_chip;
	unsigned long flags;

	nmk_chip = nmk_gpio_chips[gpio / NMK_GPIO_PER_CHIP];
	if (!nmk_chip)
		return -EINVAL;

	clk_enable(nmk_chip->clk);
	spin_lock_irqsave(&nmk_chip->lock, flags);
	__nmk_gpio_set_mode(nmk_chip, gpio % NMK_GPIO_PER_CHIP, gpio_mode);
	spin_unlock_irqrestore(&nmk_chip->lock, flags);
	clk_disable(nmk_chip->clk);

	return 0;
}
コード例 #5
0
int nmk_pin_config_set(struct pinctrl_dev *pctldev,
		       unsigned pin,
		       unsigned long config)
{
	static const char *pullnames[] = {
		[NMK_GPIO_PULL_NONE]	= "none",
		[NMK_GPIO_PULL_UP]	= "up",
		[NMK_GPIO_PULL_DOWN]	= "down",
		[3] /* illegal */	= "??"
	};
	static const char *slpmnames[] = {
		[NMK_GPIO_SLPM_INPUT]		= "input/wakeup",
		[NMK_GPIO_SLPM_NOCHANGE]	= "no-change/no-wakeup",
	};
	struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
	struct nmk_gpio_chip *nmk_chip;
	struct pinctrl_gpio_range *range;
	struct gpio_chip *chip;
	unsigned bit;

	/*
	 * The pin config contains pin number and altfunction fields, here
	 * we just ignore that part. It's being handled by the framework and
	 * pinmux callback respectively.
	 */
	pin_cfg_t cfg = (pin_cfg_t) config;
	int pull = PIN_PULL(cfg);
	int slpm = PIN_SLPM(cfg);
	int output = PIN_DIR(cfg);
	int val = PIN_VAL(cfg);
	bool lowemi = PIN_LOWEMI(cfg);
	bool gpiomode = PIN_GPIOMODE(cfg);
	bool sleep = PIN_SLEEPMODE(cfg);

	range = nmk_match_gpio_range(pctldev, pin);
	if (!range) {
		dev_err(npct->dev, "invalid pin offset %d\n", pin);
		return -EINVAL;
	}
	if (!range->gc) {
		dev_err(npct->dev, "GPIO chip missing in range for pin %d\n",
			pin);
		return -EINVAL;
	}
	chip = range->gc;
	nmk_chip = container_of(chip, struct nmk_gpio_chip, chip);

	if (sleep) {
		int slpm_pull = PIN_SLPM_PULL(cfg);
		int slpm_output = PIN_SLPM_DIR(cfg);
		int slpm_val = PIN_SLPM_VAL(cfg);

		/* All pins go into GPIO mode at sleep */
		gpiomode = true;

		/*
		 * The SLPM_* values are normal values + 1 to allow zero to
		 * mean "same as normal".
		 */
		if (slpm_pull)
			pull = slpm_pull - 1;
		if (slpm_output)
			output = slpm_output - 1;
		if (slpm_val)
			val = slpm_val - 1;

		dev_dbg(nmk_chip->chip.dev, "pin %d: sleep pull %s, dir %s, val %s\n",
			pin,
			slpm_pull ? pullnames[pull] : "same",
			slpm_output ? (output ? "output" : "input") : "same",
			slpm_val ? (val ? "high" : "low") : "same");
	}

	dev_dbg(nmk_chip->chip.dev, "pin %d [%#lx]: pull %s, slpm %s (%s%s), lowemi %s\n",
		pin, cfg, pullnames[pull], slpmnames[slpm],
		output ? "output " : "input",
		output ? (val ? "high" : "low") : "",
		lowemi ? "on" : "off" );

	clk_enable(nmk_chip->clk);
	bit = pin % NMK_GPIO_PER_CHIP;
	if (gpiomode)
		/* No glitch when going to GPIO mode */
		__nmk_gpio_set_mode(nmk_chip, bit, NMK_GPIO_ALT_GPIO);
	if (output)
		__nmk_gpio_make_output(nmk_chip, bit, val);
	else {
		__nmk_gpio_make_input(nmk_chip, bit);
		__nmk_gpio_set_pull(nmk_chip, bit, pull);
	}
	/* TODO: isn't this only applicable on output pins? */
	__nmk_gpio_set_lowemi(nmk_chip, bit, lowemi);

	__nmk_gpio_set_slpm(nmk_chip, bit, slpm);
	clk_disable(nmk_chip->clk);
	return 0;
}