// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) ST-Ericsson SA 2013 * * Author: Patrice Chotard <patrice.chotard@st.com> * * Driver allows to use AxB5xx unused pins to be used as GPIO
*/
/* set the output as 1 or 0 */ return abx500_gpio_set_bits(chip, AB8500_GPIO_OUT1_REG, offset, val);
}
staticint abx500_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
{ /* set the register as input */ return abx500_gpio_set_bits(chip,
AB8500_GPIO_DIR1_REG,
offset,
ABX500_GPIO_INPUT);
}
staticint abx500_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{ struct abx500_pinctrl *pct = gpiochip_get_data(chip); /* The AB8500 GPIO numbers are off by one */ int gpio = offset + 1; int hwirq; int i;
for (i = 0; i < pct->irq_cluster_size; i++) { struct abx500_gpio_irq_cluster *cluster =
&pct->irq_cluster[i];
if (gpio >= cluster->start && gpio <= cluster->end) { /* * The ABx500 GPIO's associated IRQs are clustered together * throughout the interrupt numbers at irregular intervals. * To solve this quandry, we have placed the read-in values * into the cluster information table.
*/
hwirq = gpio - cluster->start + cluster->to_irq; return irq_create_mapping(pct->parent->domain, hwirq);
}
}
return -EINVAL;
}
staticint abx500_set_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip, unsigned gpio, int alt_setting)
{ struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev); struct alternate_functions af = pct->soc->alternate_functions[gpio]; int ret; int val; unsigned offset;
/* on ABx5xx, there is no GPIO0, so adjust the offset */
offset = gpio - 1;
switch (alt_setting) { case ABX500_DEFAULT: /* * for ABx5xx family, default mode is always selected by * writing 0 to GPIOSELx register, except for pins which * support at least ALT_B mode, default mode is selected * by writing 1 to GPIOSELx register
*/
val = 0; if (af.alt_bit1 != UNUSED)
val++;
ret = abx500_gpio_set_bits(chip, AB8500_GPIO_SEL1_REG,
offset, val); break;
case ABX500_ALT_A: /* * for ABx5xx family, alt_a mode is always selected by * writing 1 to GPIOSELx register, except for pins which * support at least ALT_B mode, alt_a mode is selected * by writing 0 to GPIOSELx register and 0 in ALTFUNC * register
*/ if (af.alt_bit1 != UNUSED) {
ret = abx500_gpio_set_bits(chip, AB8500_GPIO_SEL1_REG,
offset, 0); if (ret < 0) goto out;
ret = abx500_gpio_set_bits(chip,
AB8500_GPIO_ALTFUN_REG,
af.alt_bit1,
!!(af.alta_val & BIT(0))); if (ret < 0) goto out;
if (af.alt_bit2 != UNUSED)
ret = abx500_gpio_set_bits(chip,
AB8500_GPIO_ALTFUN_REG,
af.alt_bit2,
!!(af.alta_val & BIT(1)));
} else
ret = abx500_gpio_set_bits(chip, AB8500_GPIO_SEL1_REG,
offset, 1); break;
case ABX500_ALT_B:
ret = abx500_gpio_set_bits(chip, AB8500_GPIO_SEL1_REG,
offset, 0); if (ret < 0) goto out;
ret = abx500_gpio_set_bits(chip, AB8500_GPIO_ALTFUN_REG,
af.alt_bit1, !!(af.altb_val & BIT(0))); if (ret < 0) goto out;
if (af.alt_bit2 != UNUSED)
ret = abx500_gpio_set_bits(chip,
AB8500_GPIO_ALTFUN_REG,
af.alt_bit2,
!!(af.altb_val & BIT(1))); break;
case ABX500_ALT_C:
ret = abx500_gpio_set_bits(chip, AB8500_GPIO_SEL1_REG,
offset, 0); if (ret < 0) goto out;
ret = abx500_gpio_set_bits(chip, AB8500_GPIO_ALTFUN_REG,
af.alt_bit2, !!(af.altc_val & BIT(0))); if (ret < 0) goto out;
ret = abx500_gpio_set_bits(chip, AB8500_GPIO_ALTFUN_REG,
af.alt_bit2, !!(af.altc_val & BIT(1))); break;
/* sanity check */ if ((af.alt_bit1 < UNUSED) || (af.alt_bit1 > 7) ||
(af.alt_bit2 < UNUSED) || (af.alt_bit2 > 7)) {
dev_err(pct->dev, "alt_bitX value not in correct range (-1 to 7)\n"); return -EINVAL;
}
/* if alt_bit2 is used, alt_bit1 must be used too */ if ((af.alt_bit2 != UNUSED) && (af.alt_bit1 == UNUSED)) {
dev_err(pct->dev, "if alt_bit2 is used, alt_bit1 can't be unused\n"); return -EINVAL;
}
/* check if pin use AlternateFunction register */ if ((af.alt_bit1 == UNUSED) && (af.alt_bit2 == UNUSED)) return mode; /* * if pin GPIOSEL bit is set and pin supports alternate function, * it means DEFAULT mode
*/ if (mode) return ABX500_DEFAULT;
/* * pin use the AlternatFunction register * read alt_bit1 value
*/
ret = abx500_gpio_get_bit(chip, AB8500_GPIO_ALTFUN_REG,
af.alt_bit1, &alt_bit1); if (ret < 0) goto out;
if (af.alt_bit2 != UNUSED) { /* read alt_bit2 value */
ret = abx500_gpio_get_bit(chip, AB8500_GPIO_ALTFUN_REG,
af.alt_bit2,
&alt_bit2); if (ret < 0) goto out;
} else
alt_bit2 = 0;
for (i = 0; i < chip->ngpio; i++, gpio++) { /* On AB8500, there is no GPIO0, the first is the GPIO 1 */
abx500_gpio_dbg_show_one(s, pctldev, chip, i + 1, gpio);
seq_putc(s, '\n');
}
}
/* * Different ranges have different ways to enable GPIO function on a * pin, so refer back to our local range type, where we handily define * what altfunc enables GPIO for a certain pin.
*/ for (i = 0; i < pct->soc->gpio_num_ranges; i++) {
p = &pct->soc->gpio_ranges[i]; if ((offset >= p->offset) &&
(offset < (p->offset + p->npins))) break;
}
if (i == pct->soc->gpio_num_ranges) {
dev_err(pct->dev, "%s failed to locate range\n", __func__); return -ENODEV;
}
dev_dbg(pct->dev, "enable GPIO by altfunc %d at gpio %d\n",
p->altfunc, offset);
ret = abx500_set_mode(pct->pctldev, &pct->chip,
offset, p->altfunc); if (ret < 0)
dev_err(pct->dev, "%s setting altfunc failed\n", __func__);
staticconstchar *abx500_find_pin_name(struct pinctrl_dev *pctldev, constchar *pin_name)
{ int i, pin_number; struct abx500_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
if (sscanf((char *)pin_name, "GPIO%d", &pin_number) == 1) for (i = 0; i < npct->soc->npins; i++) if (npct->soc->pins[i].number == pin_number) return npct->soc->pins[i].name; return NULL;
}
/* on ABx500, there is no GPIO0, so adjust the offset */
offset = pin - 1;
switch (param) { case PIN_CONFIG_BIAS_DISABLE:
ret = abx500_gpio_direction_input(chip, offset); if (ret < 0) goto out;
/* Chip only supports pull down */
ret = abx500_gpio_set_bits(chip,
AB8500_GPIO_PUD1_REG, offset,
ABX500_GPIO_PULL_NONE); break;
case PIN_CONFIG_BIAS_PULL_DOWN:
ret = abx500_gpio_direction_input(chip, offset); if (ret < 0) goto out; /* * if argument = 1 set the pull down * else clear the pull down * Chip only supports pull down
*/
ret = abx500_gpio_set_bits(chip,
AB8500_GPIO_PUD1_REG,
offset,
argument ? ABX500_GPIO_PULL_DOWN :
ABX500_GPIO_PULL_NONE); break;
case PIN_CONFIG_BIAS_PULL_UP:
ret = abx500_gpio_direction_input(chip, offset); if (ret < 0) goto out; /* * if argument = 1 set the pull up * else clear the pull up
*/
ret = abx500_gpio_direction_input(chip, offset); break;
case PIN_CONFIG_OUTPUT:
ret = abx500_gpio_direction_output(chip, offset,
argument); break;
default:
dev_err(chip->parent, "illegal configuration requested\n");
}
} /* for each config */
out: if (ret < 0)
dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
/* * Compute number of GPIOs from the last SoC gpio range descriptors * These ranges may include "holes" but the GPIO number space shall * still be homogeneous, so we need to detect and account for any * such holes so that these are included in the number of GPIO pins.
*/ for (i = 0; i < soc->gpio_num_ranges; i++) { unsigned gstart; unsigned gend; conststruct abx500_pinrange *p;
id = (unsignedlong)device_get_match_data(&pdev->dev);
/* Poke in other ASIC variants here */ switch (id) { case PINCTRL_AB8500:
abx500_pinctrl_ab8500_init(&pct->soc); break; case PINCTRL_AB8505:
abx500_pinctrl_ab8505_init(&pct->soc); break; default:
dev_err(&pdev->dev, "Unsupported pinctrl sub driver (%d)\n", id); return -EINVAL;
}
if (!pct->soc) {
dev_err(&pdev->dev, "Invalid SOC data\n"); return -EINVAL;
}
/* We will handle a range of GPIO pins */ for (i = 0; i < pct->soc->gpio_num_ranges; i++) { conststruct abx500_pinrange *p = &pct->soc->gpio_ranges[i];
ret = gpiochip_add_pin_range(&pct->chip,
dev_name(&pdev->dev),
p->offset - 1, p->offset, p->npins); if (ret < 0) goto out_rem_chip;
}
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.