static int byt_pin_config_set()

in intel/pinctrl-baytrail.c [979:1110]


static int byt_pin_config_set(struct pinctrl_dev *pctl_dev,
			      unsigned int offset,
			      unsigned long *configs,
			      unsigned int num_configs)
{
	struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctl_dev);
	unsigned int param, arg;
	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 *db_reg = byt_gpio_reg(vg, offset, BYT_DEBOUNCE_REG);
	unsigned long flags;
	u32 conf, val, debounce;
	int i, ret = 0;

	raw_spin_lock_irqsave(&byt_lock, flags);

	conf = readl(conf_reg);
	val = readl(val_reg);

	for (i = 0; i < num_configs; i++) {
		param = pinconf_to_config_param(configs[i]);
		arg = pinconf_to_config_argument(configs[i]);

		switch (param) {
		case PIN_CONFIG_BIAS_DISABLE:
			conf &= ~BYT_PULL_ASSIGN_MASK;
			break;
		case PIN_CONFIG_BIAS_PULL_DOWN:
			/* Set default strength value in case none is given */
			if (arg == 1)
				arg = 2000;

			/*
			 * Pull assignment is only applicable in input mode. If
			 * chip is not in input mode, set it and warn about it.
			 */
			if (val & BYT_INPUT_EN) {
				val &= ~BYT_INPUT_EN;
				writel(val, val_reg);
				dev_warn(vg->dev,
					 "pin %u forcibly set to input mode\n",
					 offset);
			}

			conf &= ~BYT_PULL_ASSIGN_MASK;
			conf |= BYT_PULL_ASSIGN_DOWN;
			ret = byt_set_pull_strength(&conf, arg);

			break;
		case PIN_CONFIG_BIAS_PULL_UP:
			/* Set default strength value in case none is given */
			if (arg == 1)
				arg = 2000;

			/*
			 * Pull assignment is only applicable in input mode. If
			 * chip is not in input mode, set it and warn about it.
			 */
			if (val & BYT_INPUT_EN) {
				val &= ~BYT_INPUT_EN;
				writel(val, val_reg);
				dev_warn(vg->dev,
					 "pin %u forcibly set to input mode\n",
					 offset);
			}

			conf &= ~BYT_PULL_ASSIGN_MASK;
			conf |= BYT_PULL_ASSIGN_UP;
			ret = byt_set_pull_strength(&conf, arg);

			break;
		case PIN_CONFIG_INPUT_DEBOUNCE:
			debounce = readl(db_reg);

			if (arg)
				conf |= BYT_DEBOUNCE_EN;
			else
				conf &= ~BYT_DEBOUNCE_EN;

			switch (arg) {
			case 375:
				debounce &= ~BYT_DEBOUNCE_PULSE_MASK;
				debounce |= BYT_DEBOUNCE_PULSE_375US;
				break;
			case 750:
				debounce &= ~BYT_DEBOUNCE_PULSE_MASK;
				debounce |= BYT_DEBOUNCE_PULSE_750US;
				break;
			case 1500:
				debounce &= ~BYT_DEBOUNCE_PULSE_MASK;
				debounce |= BYT_DEBOUNCE_PULSE_1500US;
				break;
			case 3000:
				debounce &= ~BYT_DEBOUNCE_PULSE_MASK;
				debounce |= BYT_DEBOUNCE_PULSE_3MS;
				break;
			case 6000:
				debounce &= ~BYT_DEBOUNCE_PULSE_MASK;
				debounce |= BYT_DEBOUNCE_PULSE_6MS;
				break;
			case 12000:
				debounce &= ~BYT_DEBOUNCE_PULSE_MASK;
				debounce |= BYT_DEBOUNCE_PULSE_12MS;
				break;
			case 24000:
				debounce &= ~BYT_DEBOUNCE_PULSE_MASK;
				debounce |= BYT_DEBOUNCE_PULSE_24MS;
				break;
			default:
				if (arg)
					ret = -EINVAL;
				break;
			}

			if (!ret)
				writel(debounce, db_reg);
			break;
		default:
			ret = -ENOTSUPP;
		}

		if (ret)
			break;
	}

	if (!ret)
		writel(conf, conf_reg);

	raw_spin_unlock_irqrestore(&byt_lock, flags);

	return ret;
}