gpio: sim: allow to mark simulated lines as invalid
Add a new line-level, boolean property to the gpio-sim configfs interface called 'valid'. It's set by default and the user can unset it to make the line be included in the standard `gpio-reserved-ranges` property when the chip is registered with GPIO core. This allows users to specify which lines should not be available for requesting as GPIOs. Link: https://lore.kernel.org/r/20250630130358.40352-1-brgl@bgdev.pl Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>pull/1309/head
parent
6c99a046ed
commit
0cf6d425d3
|
|
@ -50,8 +50,11 @@ the number of lines exposed by this bank.
|
|||
|
||||
**Attribute:** ``/config/gpio-sim/gpio-device/gpio-bankX/lineY/name``
|
||||
|
||||
This group represents a single line at the offset Y. The 'name' attribute
|
||||
allows to set the line name as represented by the 'gpio-line-names' property.
|
||||
**Attribute:** ``/config/gpio-sim/gpio-device/gpio-bankX/lineY/valid``
|
||||
|
||||
This group represents a single line at the offset Y. The ``valid`` attribute
|
||||
indicates whether the line can be used as GPIO. The ``name`` attribute allows
|
||||
to set the line name as represented by the 'gpio-line-names' property.
|
||||
|
||||
**Item:** ``/config/gpio-sim/gpio-device/gpio-bankX/lineY/hog``
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
#include "dev-sync-probe.h"
|
||||
|
||||
#define GPIO_SIM_NGPIO_MAX 1024
|
||||
#define GPIO_SIM_PROP_MAX 4 /* Max 3 properties + sentinel. */
|
||||
#define GPIO_SIM_PROP_MAX 5 /* Max 4 properties + sentinel. */
|
||||
#define GPIO_SIM_NUM_ATTRS 3 /* value, pull and sentinel */
|
||||
|
||||
static DEFINE_IDA(gpio_sim_ida);
|
||||
|
|
@ -629,6 +629,7 @@ struct gpio_sim_line {
|
|||
|
||||
unsigned int offset;
|
||||
char *name;
|
||||
bool valid;
|
||||
|
||||
/* There can only be one hog per line. */
|
||||
struct gpio_sim_hog *hog;
|
||||
|
|
@ -744,6 +745,36 @@ gpio_sim_set_line_names(struct gpio_sim_bank *bank, char **line_names)
|
|||
}
|
||||
}
|
||||
|
||||
static unsigned int gpio_sim_get_reserved_ranges_size(struct gpio_sim_bank *bank)
|
||||
{
|
||||
struct gpio_sim_line *line;
|
||||
unsigned int size = 0;
|
||||
|
||||
list_for_each_entry(line, &bank->line_list, siblings) {
|
||||
if (line->valid)
|
||||
continue;
|
||||
|
||||
size += 2;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static void gpio_sim_set_reserved_ranges(struct gpio_sim_bank *bank,
|
||||
u32 *ranges)
|
||||
{
|
||||
struct gpio_sim_line *line;
|
||||
int i = 0;
|
||||
|
||||
list_for_each_entry(line, &bank->line_list, siblings) {
|
||||
if (line->valid)
|
||||
continue;
|
||||
|
||||
ranges[i++] = line->offset;
|
||||
ranges[i++] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void gpio_sim_remove_hogs(struct gpio_sim_device *dev)
|
||||
{
|
||||
struct gpiod_hog *hog;
|
||||
|
|
@ -844,9 +875,10 @@ static struct fwnode_handle *
|
|||
gpio_sim_make_bank_swnode(struct gpio_sim_bank *bank,
|
||||
struct fwnode_handle *parent)
|
||||
{
|
||||
unsigned int prop_idx = 0, line_names_size, ranges_size;
|
||||
struct property_entry properties[GPIO_SIM_PROP_MAX];
|
||||
unsigned int prop_idx = 0, line_names_size;
|
||||
char **line_names __free(kfree) = NULL;
|
||||
u32 *ranges __free(kfree) = NULL;
|
||||
|
||||
memset(properties, 0, sizeof(properties));
|
||||
|
||||
|
|
@ -870,6 +902,19 @@ gpio_sim_make_bank_swnode(struct gpio_sim_bank *bank,
|
|||
line_names, line_names_size);
|
||||
}
|
||||
|
||||
ranges_size = gpio_sim_get_reserved_ranges_size(bank);
|
||||
if (ranges_size) {
|
||||
ranges = kcalloc(ranges_size, sizeof(u32), GFP_KERNEL);
|
||||
if (!ranges)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
gpio_sim_set_reserved_ranges(bank, ranges);
|
||||
|
||||
properties[prop_idx++] = PROPERTY_ENTRY_U32_ARRAY_LEN(
|
||||
"gpio-reserved-ranges",
|
||||
ranges, ranges_size);
|
||||
}
|
||||
|
||||
return fwnode_create_software_node(properties, parent);
|
||||
}
|
||||
|
||||
|
|
@ -1189,8 +1234,41 @@ static ssize_t gpio_sim_line_config_name_store(struct config_item *item,
|
|||
|
||||
CONFIGFS_ATTR(gpio_sim_line_config_, name);
|
||||
|
||||
static ssize_t
|
||||
gpio_sim_line_config_valid_show(struct config_item *item, char *page)
|
||||
{
|
||||
struct gpio_sim_line *line = to_gpio_sim_line(item);
|
||||
struct gpio_sim_device *dev = gpio_sim_line_get_device(line);
|
||||
|
||||
guard(mutex)(&dev->lock);
|
||||
|
||||
return sprintf(page, "%c\n", line->valid ? '1' : '0');
|
||||
}
|
||||
|
||||
static ssize_t gpio_sim_line_config_valid_store(struct config_item *item,
|
||||
const char *page, size_t count)
|
||||
{
|
||||
struct gpio_sim_line *line = to_gpio_sim_line(item);
|
||||
struct gpio_sim_device *dev = gpio_sim_line_get_device(line);
|
||||
bool valid;
|
||||
int ret;
|
||||
|
||||
ret = kstrtobool(page, &valid);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
guard(mutex)(&dev->lock);
|
||||
|
||||
line->valid = valid;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
CONFIGFS_ATTR(gpio_sim_line_config_, valid);
|
||||
|
||||
static struct configfs_attribute *gpio_sim_line_config_attrs[] = {
|
||||
&gpio_sim_line_config_attr_name,
|
||||
&gpio_sim_line_config_attr_valid,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
@ -1399,6 +1477,7 @@ gpio_sim_bank_config_make_line_group(struct config_group *group,
|
|||
|
||||
line->parent = bank;
|
||||
line->offset = offset;
|
||||
line->valid = true;
|
||||
list_add_tail(&line->siblings, &bank->line_list);
|
||||
|
||||
return &line->group;
|
||||
|
|
|
|||
Loading…
Reference in New Issue