Merge branch 'gpio-reserved-ranges' into devel

This commit is contained in:
Linus Walleij 2018-03-27 15:34:40 +02:00
commit 89b0b4e2d3
5 changed files with 167 additions and 11 deletions

View File

@ -151,9 +151,9 @@ in a lot of designs, some using all 32 bits, some using 18 and some using
first 18 GPIOs, at local offset 0 .. 17, are in use.
If these GPIOs do not happen to be the first N GPIOs at offset 0...N-1, an
additional bitmask is needed to specify which GPIOs are actually in use,
and which are dummies. The bindings for this case has not yet been
specified, but should be specified if/when such hardware appears.
additional set of tuples is needed to specify which GPIOs are unusable, with
the gpio-reserved-ranges binding. This property indicates the start and size
of the GPIOs that can't be used.
Optionally, a GPIO controller may have a "gpio-line-names" property. This is
an array of strings defining the names of the GPIO lines going out of the
@ -178,6 +178,7 @@ gpio-controller@00000000 {
gpio-controller;
#gpio-cells = <2>;
ngpios = <18>;
gpio-reserved-ranges = <0 4>, <12 2>;
gpio-line-names = "MMC-CD", "MMC-WP", "VDD eth", "RST eth", "LED R",
"LED G", "LED B", "Col A", "Col B", "Col C", "Col D",
"Row A", "Row B", "Row C", "Row D", "NMI button",

View File

@ -511,6 +511,28 @@ void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc)
}
EXPORT_SYMBOL(of_mm_gpiochip_remove);
static void of_gpiochip_init_valid_mask(struct gpio_chip *chip)
{
int len, i;
u32 start, count;
struct device_node *np = chip->of_node;
len = of_property_count_u32_elems(np, "gpio-reserved-ranges");
if (len < 0 || len % 2 != 0)
return;
for (i = 0; i < len; i += 2) {
of_property_read_u32_index(np, "gpio-reserved-ranges",
i, &start);
of_property_read_u32_index(np, "gpio-reserved-ranges",
i + 1, &count);
if (start >= chip->ngpio || start + count >= chip->ngpio)
continue;
bitmap_clear(chip->valid_mask, start, count);
}
};
#ifdef CONFIG_PINCTRL
static int of_gpiochip_add_pin_range(struct gpio_chip *chip)
{
@ -615,6 +637,8 @@ int of_gpiochip_add(struct gpio_chip *chip)
if (chip->of_gpio_n_cells > MAX_PHANDLE_ARGS)
return -EINVAL;
of_gpiochip_init_valid_mask(chip);
status = of_gpiochip_add_pin_range(chip);
if (status)
return status;

View File

@ -337,6 +337,57 @@ static int gpiochip_set_desc_names(struct gpio_chip *gc)
return 0;
}
static unsigned long *gpiochip_allocate_mask(struct gpio_chip *chip)
{
unsigned long *p;
p = kmalloc_array(BITS_TO_LONGS(chip->ngpio), sizeof(*p), GFP_KERNEL);
if (!p)
return NULL;
/* Assume by default all GPIOs are valid */
bitmap_fill(p, chip->ngpio);
return p;
}
static int gpiochip_init_valid_mask(struct gpio_chip *gpiochip)
{
#ifdef CONFIG_OF_GPIO
int size;
struct device_node *np = gpiochip->of_node;
size = of_property_count_u32_elems(np, "gpio-reserved-ranges");
if (size > 0 && size % 2 == 0)
gpiochip->need_valid_mask = true;
#endif
if (!gpiochip->need_valid_mask)
return 0;
gpiochip->valid_mask = gpiochip_allocate_mask(gpiochip);
if (!gpiochip->valid_mask)
return -ENOMEM;
return 0;
}
static void gpiochip_free_valid_mask(struct gpio_chip *gpiochip)
{
kfree(gpiochip->valid_mask);
gpiochip->valid_mask = NULL;
}
bool gpiochip_line_is_valid(const struct gpio_chip *gpiochip,
unsigned int offset)
{
/* No mask means all valid */
if (likely(!gpiochip->valid_mask))
return true;
return test_bit(offset, gpiochip->valid_mask);
}
EXPORT_SYMBOL_GPL(gpiochip_line_is_valid);
/*
* GPIO line handle management
*/
@ -1261,6 +1312,10 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
if (status)
goto err_remove_from_list;
status = gpiochip_init_valid_mask(chip);
if (status)
goto err_remove_irqchip_mask;
status = gpiochip_add_irqchip(chip, lock_key, request_key);
if (status)
goto err_remove_chip;
@ -1290,6 +1345,8 @@ err_remove_chip:
acpi_gpiochip_remove(chip);
gpiochip_free_hogs(chip);
of_gpiochip_remove(chip);
gpiochip_free_valid_mask(chip);
err_remove_irqchip_mask:
gpiochip_irqchip_free_valid_mask(chip);
err_remove_from_list:
spin_lock_irqsave(&gpio_lock, flags);
@ -1346,6 +1403,7 @@ void gpiochip_remove(struct gpio_chip *chip)
acpi_gpiochip_remove(chip);
gpiochip_remove_pin_ranges(chip);
of_gpiochip_remove(chip);
gpiochip_free_valid_mask(chip);
/*
* We accept no more calls into the driver from this point, so
* NULL the driver data pointer
@ -1506,14 +1564,10 @@ static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gpiochip)
if (!gpiochip->irq.need_valid_mask)
return 0;
gpiochip->irq.valid_mask = kcalloc(BITS_TO_LONGS(gpiochip->ngpio),
sizeof(long), GFP_KERNEL);
gpiochip->irq.valid_mask = gpiochip_allocate_mask(gpiochip);
if (!gpiochip->irq.valid_mask)
return -ENOMEM;
/* Assume by default all GPIOs are valid */
bitmap_fill(gpiochip->irq.valid_mask, gpiochip->ngpio);
return 0;
}
@ -1526,6 +1580,8 @@ static void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gpiochip)
bool gpiochip_irqchip_irq_valid(const struct gpio_chip *gpiochip,
unsigned int offset)
{
if (!gpiochip_line_is_valid(gpiochip, offset))
return false;
/* No mask means all valid */
if (likely(!gpiochip->irq.valid_mask))
return true;

View File

@ -105,6 +105,14 @@ static const struct pinctrl_ops msm_pinctrl_ops = {
.dt_free_map = pinctrl_utils_free_map,
};
static int msm_pinmux_request(struct pinctrl_dev *pctldev, unsigned offset)
{
struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
struct gpio_chip *chip = &pctrl->chip;
return gpiochip_line_is_valid(chip, offset) ? 0 : -EINVAL;
}
static int msm_get_functions_count(struct pinctrl_dev *pctldev)
{
struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
@ -166,6 +174,7 @@ static int msm_pinmux_set_mux(struct pinctrl_dev *pctldev,
}
static const struct pinmux_ops msm_pinmux_ops = {
.request = msm_pinmux_request,
.get_functions_count = msm_get_functions_count,
.get_function_name = msm_get_function_name,
.get_function_groups = msm_get_function_groups,
@ -506,6 +515,9 @@ static void msm_gpio_dbg_show_one(struct seq_file *s,
"pull up"
};
if (!gpiochip_line_is_valid(chip, offset))
return;
g = &pctrl->soc->groups[offset];
ctl_reg = readl(pctrl->regs + g->ctl_reg);
@ -517,6 +529,7 @@ static void msm_gpio_dbg_show_one(struct seq_file *s,
seq_printf(s, " %-8s: %-3s %d", g->name, is_out ? "out" : "in", func);
seq_printf(s, " %dmA", msm_regval_to_drive(drive));
seq_printf(s, " %s", pulls[pull]);
seq_puts(s, "\n");
}
static void msm_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
@ -524,10 +537,8 @@ static void msm_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
unsigned gpio = chip->base;
unsigned i;
for (i = 0; i < chip->ngpio; i++, gpio++) {
for (i = 0; i < chip->ngpio; i++, gpio++)
msm_gpio_dbg_show_one(s, NULL, chip, i, gpio);
seq_puts(s, "\n");
}
}
#else
@ -808,6 +819,46 @@ static void msm_gpio_irq_handler(struct irq_desc *desc)
chained_irq_exit(chip, desc);
}
static int msm_gpio_init_valid_mask(struct gpio_chip *chip,
struct msm_pinctrl *pctrl)
{
int ret;
unsigned int len, i;
unsigned int max_gpios = pctrl->soc->ngpios;
u16 *tmp;
/* The number of GPIOs in the ACPI tables */
len = ret = device_property_read_u16_array(pctrl->dev, "gpios", NULL, 0);
if (ret < 0)
return 0;
if (ret > max_gpios)
return -EINVAL;
tmp = kmalloc_array(len, sizeof(*tmp), GFP_KERNEL);
if (!tmp)
return -ENOMEM;
ret = device_property_read_u16_array(pctrl->dev, "gpios", tmp, len);
if (ret < 0) {
dev_err(pctrl->dev, "could not read list of GPIOs\n");
goto out;
}
bitmap_zero(chip->valid_mask, max_gpios);
for (i = 0; i < len; i++)
set_bit(tmp[i], chip->valid_mask);
out:
kfree(tmp);
return ret;
}
static bool msm_gpio_needs_valid_mask(struct msm_pinctrl *pctrl)
{
return device_property_read_u16_array(pctrl->dev, "gpios", NULL, 0) > 0;
}
static int msm_gpio_init(struct msm_pinctrl *pctrl)
{
struct gpio_chip *chip;
@ -824,6 +875,7 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl)
chip->parent = pctrl->dev;
chip->owner = THIS_MODULE;
chip->of_node = pctrl->dev->of_node;
chip->need_valid_mask = msm_gpio_needs_valid_mask(pctrl);
ret = gpiochip_add_data(&pctrl->chip, pctrl);
if (ret) {
@ -831,6 +883,13 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl)
return ret;
}
ret = msm_gpio_init_valid_mask(chip, pctrl);
if (ret) {
dev_err(pctrl->dev, "Failed to setup irq valid bits\n");
gpiochip_remove(&pctrl->chip);
return ret;
}
ret = gpiochip_add_pin_range(&pctrl->chip, dev_name(pctrl->dev), 0, 0, chip->ngpio);
if (ret) {
dev_err(pctrl->dev, "Failed to add pin range\n");

View File

@ -288,6 +288,21 @@ struct gpio_chip {
struct gpio_irq_chip irq;
#endif
/**
* @need_valid_mask:
*
* If set core allocates @valid_mask with all bits set to one.
*/
bool need_valid_mask;
/**
* @valid_mask:
*
* If not %NULL holds bitmask of GPIOs which are valid to be used
* from the chip.
*/
unsigned long *valid_mask;
#if defined(CONFIG_OF_GPIO)
/*
* If CONFIG_OF is enabled, then all GPIO controllers described in the
@ -384,6 +399,7 @@ bool gpiochip_line_is_open_source(struct gpio_chip *chip, unsigned int offset);
/* Sleep persistence inquiry for drivers */
bool gpiochip_line_is_persistent(struct gpio_chip *chip, unsigned int offset);
bool gpiochip_line_is_valid(const struct gpio_chip *chip, unsigned int offset);
/* get driver data */
void *gpiochip_get_data(struct gpio_chip *chip);