gpiolib: cdev: consolidate edge detector configuration flags
Combine the polarity_change flag, struct line eflags, and hte enable flag into a single flag variable. The combination of these flags describes the configuration state of the edge detector, so formalize and clarify that by combining them into a single variable, edflags, in struct line. The edflags is a subset of the GPIO_V2_LINE_FLAGsb relevant to the edge detector, and is also a superset of the eflags it replaces. The eflags name is still used to describe the subset of edflags corresponding to the rising/falling edge flags where edflags is masked down to that subset. This consolidation reduces the number of variables being passed, simplifies state comparisons, and provides a more extensible foundation should additional edge sources be integrated in the future. Signed-off-by: Kent Gibson <warthog618@gmail.com> Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com> Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
This commit is contained in:
parent
242202329f
commit
b1a92e9456
@ -430,12 +430,15 @@ struct line {
|
|||||||
struct linereq *req;
|
struct linereq *req;
|
||||||
unsigned int irq;
|
unsigned int irq;
|
||||||
/*
|
/*
|
||||||
* eflags is set by edge_detector_setup(), edge_detector_stop() and
|
* The flags for the active edge detector configuration.
|
||||||
* edge_detector_update(), which are themselves mutually exclusive,
|
*
|
||||||
* and is accessed by edge_irq_thread() and debounce_work_func(),
|
* edflags is set by linereq_create(), linereq_free(), and
|
||||||
* which can both live with a slightly stale value.
|
* linereq_set_config_unlocked(), which are themselves mutually
|
||||||
|
* exclusive, and is accessed by edge_irq_thread(),
|
||||||
|
* process_hw_ts_thread() and debounce_work_func(),
|
||||||
|
* which can all live with a slightly stale value.
|
||||||
*/
|
*/
|
||||||
u64 eflags;
|
u64 edflags;
|
||||||
/*
|
/*
|
||||||
* timestamp_ns and req_seqno are accessed only by
|
* timestamp_ns and req_seqno are accessed only by
|
||||||
* edge_irq_handler() and edge_irq_thread(), which are themselves
|
* edge_irq_handler() and edge_irq_thread(), which are themselves
|
||||||
@ -541,6 +544,12 @@ struct linereq {
|
|||||||
GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE | \
|
GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE | \
|
||||||
GPIO_V2_LINE_BIAS_FLAGS)
|
GPIO_V2_LINE_BIAS_FLAGS)
|
||||||
|
|
||||||
|
/* subset of flags relevant for edge detector configuration */
|
||||||
|
#define GPIO_V2_LINE_EDGE_DETECTOR_FLAGS \
|
||||||
|
(GPIO_V2_LINE_FLAG_ACTIVE_LOW | \
|
||||||
|
GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE | \
|
||||||
|
GPIO_V2_LINE_EDGE_FLAGS)
|
||||||
|
|
||||||
static void linereq_put_event(struct linereq *lr,
|
static void linereq_put_event(struct linereq *lr,
|
||||||
struct gpio_v2_line_event *le)
|
struct gpio_v2_line_event *le)
|
||||||
{
|
{
|
||||||
@ -580,8 +589,8 @@ static enum hte_return process_hw_ts_thread(void *p)
|
|||||||
struct line *line;
|
struct line *line;
|
||||||
struct linereq *lr;
|
struct linereq *lr;
|
||||||
struct gpio_v2_line_event le;
|
struct gpio_v2_line_event le;
|
||||||
|
u64 edflags;
|
||||||
int level;
|
int level;
|
||||||
u64 eflags;
|
|
||||||
|
|
||||||
if (!p)
|
if (!p)
|
||||||
return HTE_CB_HANDLED;
|
return HTE_CB_HANDLED;
|
||||||
@ -592,15 +601,15 @@ static enum hte_return process_hw_ts_thread(void *p)
|
|||||||
memset(&le, 0, sizeof(le));
|
memset(&le, 0, sizeof(le));
|
||||||
|
|
||||||
le.timestamp_ns = line->timestamp_ns;
|
le.timestamp_ns = line->timestamp_ns;
|
||||||
eflags = READ_ONCE(line->eflags);
|
edflags = READ_ONCE(line->edflags);
|
||||||
|
|
||||||
switch (eflags) {
|
switch (edflags & GPIO_V2_LINE_EDGE_FLAGS) {
|
||||||
case GPIO_V2_LINE_FLAG_EDGE_BOTH:
|
case GPIO_V2_LINE_FLAG_EDGE_BOTH:
|
||||||
level = (line->raw_level >= 0) ?
|
level = (line->raw_level >= 0) ?
|
||||||
line->raw_level :
|
line->raw_level :
|
||||||
gpiod_get_raw_value_cansleep(line->desc);
|
gpiod_get_raw_value_cansleep(line->desc);
|
||||||
|
|
||||||
if (test_bit(FLAG_ACTIVE_LOW, &line->desc->flags))
|
if (edflags & GPIO_V2_LINE_FLAG_ACTIVE_LOW)
|
||||||
level = !level;
|
level = !level;
|
||||||
|
|
||||||
le.id = line_event_id(level);
|
le.id = line_event_id(level);
|
||||||
@ -681,7 +690,7 @@ static irqreturn_t edge_irq_thread(int irq, void *p)
|
|||||||
}
|
}
|
||||||
line->timestamp_ns = 0;
|
line->timestamp_ns = 0;
|
||||||
|
|
||||||
switch (READ_ONCE(line->eflags)) {
|
switch (READ_ONCE(line->edflags) & GPIO_V2_LINE_EDGE_FLAGS) {
|
||||||
case GPIO_V2_LINE_FLAG_EDGE_BOTH:
|
case GPIO_V2_LINE_FLAG_EDGE_BOTH:
|
||||||
le.id = line_event_id(gpiod_get_value_cansleep(line->desc));
|
le.id = line_event_id(gpiod_get_value_cansleep(line->desc));
|
||||||
break;
|
break;
|
||||||
@ -756,16 +765,13 @@ static void debounce_work_func(struct work_struct *work)
|
|||||||
struct gpio_v2_line_event le;
|
struct gpio_v2_line_event le;
|
||||||
struct line *line = container_of(work, struct line, work.work);
|
struct line *line = container_of(work, struct line, work.work);
|
||||||
struct linereq *lr;
|
struct linereq *lr;
|
||||||
int level, diff_seqno;
|
u64 eflags, edflags = READ_ONCE(line->edflags);
|
||||||
u64 eflags;
|
int level = -1, diff_seqno;
|
||||||
|
|
||||||
if (test_bit(FLAG_EVENT_CLOCK_HTE, &line->desc->flags)) {
|
if (edflags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE)
|
||||||
level = line->raw_level;
|
level = line->raw_level;
|
||||||
if (level < 0)
|
if (level < 0)
|
||||||
level = gpiod_get_raw_value_cansleep(line->desc);
|
|
||||||
} else {
|
|
||||||
level = gpiod_get_raw_value_cansleep(line->desc);
|
level = gpiod_get_raw_value_cansleep(line->desc);
|
||||||
}
|
|
||||||
if (level < 0) {
|
if (level < 0) {
|
||||||
pr_debug_ratelimited("debouncer failed to read line value\n");
|
pr_debug_ratelimited("debouncer failed to read line value\n");
|
||||||
return;
|
return;
|
||||||
@ -777,12 +783,12 @@ static void debounce_work_func(struct work_struct *work)
|
|||||||
WRITE_ONCE(line->level, level);
|
WRITE_ONCE(line->level, level);
|
||||||
|
|
||||||
/* -- edge detection -- */
|
/* -- edge detection -- */
|
||||||
eflags = READ_ONCE(line->eflags);
|
eflags = edflags & GPIO_V2_LINE_EDGE_FLAGS;
|
||||||
if (!eflags)
|
if (!eflags)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* switch from physical level to logical - if they differ */
|
/* switch from physical level to logical - if they differ */
|
||||||
if (test_bit(FLAG_ACTIVE_LOW, &line->desc->flags))
|
if (edflags & GPIO_V2_LINE_FLAG_ACTIVE_LOW)
|
||||||
level = !level;
|
level = !level;
|
||||||
|
|
||||||
/* ignore edges that are not being monitored */
|
/* ignore edges that are not being monitored */
|
||||||
@ -796,7 +802,7 @@ static void debounce_work_func(struct work_struct *work)
|
|||||||
lr = line->req;
|
lr = line->req;
|
||||||
le.timestamp_ns = line_event_timestamp(line);
|
le.timestamp_ns = line_event_timestamp(line);
|
||||||
le.offset = gpio_chip_hwgpio(line->desc);
|
le.offset = gpio_chip_hwgpio(line->desc);
|
||||||
if (test_bit(FLAG_EVENT_CLOCK_HTE, &line->desc->flags)) {
|
if (edflags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE) {
|
||||||
/* discard events except the last one */
|
/* discard events except the last one */
|
||||||
line->total_discard_seq -= 1;
|
line->total_discard_seq -= 1;
|
||||||
diff_seqno = line->last_seqno - line->total_discard_seq -
|
diff_seqno = line->last_seqno - line->total_discard_seq -
|
||||||
@ -843,8 +849,7 @@ static int hte_edge_setup(struct line *line, u64 eflags)
|
|||||||
process_hw_ts_thread, line);
|
process_hw_ts_thread, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int debounce_setup(struct line *line,
|
static int debounce_setup(struct line *line, unsigned int debounce_period_us)
|
||||||
unsigned int debounce_period_us, bool hte_req)
|
|
||||||
{
|
{
|
||||||
unsigned long irqflags;
|
unsigned long irqflags;
|
||||||
int ret, level, irq;
|
int ret, level, irq;
|
||||||
@ -864,7 +869,7 @@ static int debounce_setup(struct line *line,
|
|||||||
if (level < 0)
|
if (level < 0)
|
||||||
return level;
|
return level;
|
||||||
|
|
||||||
if (!hte_req) {
|
if (!test_bit(FLAG_EVENT_CLOCK_HTE, &line->desc->flags)) {
|
||||||
irq = gpiod_to_irq(line->desc);
|
irq = gpiod_to_irq(line->desc);
|
||||||
if (irq < 0)
|
if (irq < 0)
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
@ -915,19 +920,19 @@ static u32 gpio_v2_line_config_debounce_period(struct gpio_v2_line_config *lc,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void edge_detector_stop(struct line *line, bool hte_en)
|
static void edge_detector_stop(struct line *line)
|
||||||
{
|
{
|
||||||
if (line->irq && !hte_en) {
|
if (line->irq) {
|
||||||
free_irq(line->irq, line);
|
free_irq(line->irq, line);
|
||||||
line->irq = 0;
|
line->irq = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hte_en)
|
if (READ_ONCE(line->edflags) & GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE)
|
||||||
hte_ts_put(&line->hdesc);
|
hte_ts_put(&line->hdesc);
|
||||||
|
|
||||||
cancel_delayed_work_sync(&line->work);
|
cancel_delayed_work_sync(&line->work);
|
||||||
WRITE_ONCE(line->sw_debounced, 0);
|
WRITE_ONCE(line->sw_debounced, 0);
|
||||||
WRITE_ONCE(line->eflags, 0);
|
WRITE_ONCE(line->edflags, 0);
|
||||||
if (line->desc)
|
if (line->desc)
|
||||||
WRITE_ONCE(line->desc->debounce_period_us, 0);
|
WRITE_ONCE(line->desc->debounce_period_us, 0);
|
||||||
/* do not change line->level - see comment in debounced_value() */
|
/* do not change line->level - see comment in debounced_value() */
|
||||||
@ -935,23 +940,23 @@ static void edge_detector_stop(struct line *line, bool hte_en)
|
|||||||
|
|
||||||
static int edge_detector_setup(struct line *line,
|
static int edge_detector_setup(struct line *line,
|
||||||
struct gpio_v2_line_config *lc,
|
struct gpio_v2_line_config *lc,
|
||||||
unsigned int line_idx,
|
unsigned int line_idx, u64 edflags)
|
||||||
u64 eflags, bool hte_req)
|
|
||||||
{
|
{
|
||||||
u32 debounce_period_us;
|
u32 debounce_period_us;
|
||||||
unsigned long irqflags = 0;
|
unsigned long irqflags = 0;
|
||||||
|
u64 eflags;
|
||||||
int irq, ret;
|
int irq, ret;
|
||||||
|
|
||||||
|
eflags = edflags & GPIO_V2_LINE_EDGE_FLAGS;
|
||||||
if (eflags && !kfifo_initialized(&line->req->events)) {
|
if (eflags && !kfifo_initialized(&line->req->events)) {
|
||||||
ret = kfifo_alloc(&line->req->events,
|
ret = kfifo_alloc(&line->req->events,
|
||||||
line->req->event_buffer_size, GFP_KERNEL);
|
line->req->event_buffer_size, GFP_KERNEL);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
WRITE_ONCE(line->eflags, eflags);
|
|
||||||
if (gpio_v2_line_config_debounced(lc, line_idx)) {
|
if (gpio_v2_line_config_debounced(lc, line_idx)) {
|
||||||
debounce_period_us = gpio_v2_line_config_debounce_period(lc, line_idx);
|
debounce_period_us = gpio_v2_line_config_debounce_period(lc, line_idx);
|
||||||
ret = debounce_setup(line, debounce_period_us, hte_req);
|
ret = debounce_setup(line, debounce_period_us);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
WRITE_ONCE(line->desc->debounce_period_us, debounce_period_us);
|
WRITE_ONCE(line->desc->debounce_period_us, debounce_period_us);
|
||||||
@ -961,8 +966,8 @@ static int edge_detector_setup(struct line *line,
|
|||||||
if (!eflags || READ_ONCE(line->sw_debounced))
|
if (!eflags || READ_ONCE(line->sw_debounced))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (hte_req)
|
if (edflags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE)
|
||||||
return hte_edge_setup(line, eflags);
|
return hte_edge_setup(line, edflags);
|
||||||
|
|
||||||
irq = gpiod_to_irq(line->desc);
|
irq = gpiod_to_irq(line->desc);
|
||||||
if (irq < 0)
|
if (irq < 0)
|
||||||
@ -988,35 +993,29 @@ static int edge_detector_setup(struct line *line,
|
|||||||
|
|
||||||
static int edge_detector_update(struct line *line,
|
static int edge_detector_update(struct line *line,
|
||||||
struct gpio_v2_line_config *lc,
|
struct gpio_v2_line_config *lc,
|
||||||
unsigned int line_idx,
|
unsigned int line_idx, u64 edflags)
|
||||||
u64 flags, bool polarity_change,
|
|
||||||
bool prev_hte_flag)
|
|
||||||
{
|
{
|
||||||
u64 eflags = flags & GPIO_V2_LINE_EDGE_FLAGS;
|
u64 active_edflags = READ_ONCE(line->edflags);
|
||||||
unsigned int debounce_period_us =
|
unsigned int debounce_period_us =
|
||||||
gpio_v2_line_config_debounce_period(lc, line_idx);
|
gpio_v2_line_config_debounce_period(lc, line_idx);
|
||||||
bool hte_change = (prev_hte_flag !=
|
|
||||||
((flags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE) != 0));
|
|
||||||
|
|
||||||
if ((READ_ONCE(line->eflags) == eflags) && !polarity_change &&
|
if ((active_edflags == edflags) &&
|
||||||
(READ_ONCE(line->desc->debounce_period_us) == debounce_period_us)
|
(READ_ONCE(line->desc->debounce_period_us) == debounce_period_us))
|
||||||
&& !hte_change)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* sw debounced and still will be...*/
|
/* sw debounced and still will be...*/
|
||||||
if (debounce_period_us && READ_ONCE(line->sw_debounced)) {
|
if (debounce_period_us && READ_ONCE(line->sw_debounced)) {
|
||||||
WRITE_ONCE(line->eflags, eflags);
|
|
||||||
WRITE_ONCE(line->desc->debounce_period_us, debounce_period_us);
|
WRITE_ONCE(line->desc->debounce_period_us, debounce_period_us);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reconfiguring edge detection or sw debounce being disabled */
|
/* reconfiguring edge detection or sw debounce being disabled */
|
||||||
if ((line->irq && !READ_ONCE(line->sw_debounced)) || prev_hte_flag ||
|
if ((line->irq && !READ_ONCE(line->sw_debounced)) ||
|
||||||
|
(active_edflags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE) ||
|
||||||
(!debounce_period_us && READ_ONCE(line->sw_debounced)))
|
(!debounce_period_us && READ_ONCE(line->sw_debounced)))
|
||||||
edge_detector_stop(line, prev_hte_flag);
|
edge_detector_stop(line);
|
||||||
|
|
||||||
return edge_detector_setup(line, lc, line_idx, eflags,
|
return edge_detector_setup(line, lc, line_idx, edflags);
|
||||||
flags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static u64 gpio_v2_line_config_flags(struct gpio_v2_line_config *lc,
|
static u64 gpio_v2_line_config_flags(struct gpio_v2_line_config *lc,
|
||||||
@ -1285,22 +1284,17 @@ static long linereq_set_config_unlocked(struct linereq *lr,
|
|||||||
struct gpio_v2_line_config *lc)
|
struct gpio_v2_line_config *lc)
|
||||||
{
|
{
|
||||||
struct gpio_desc *desc;
|
struct gpio_desc *desc;
|
||||||
|
struct line *line;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
u64 flags;
|
u64 flags, edflags;
|
||||||
bool polarity_change;
|
|
||||||
bool prev_hte_flag;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
for (i = 0; i < lr->num_lines; i++) {
|
for (i = 0; i < lr->num_lines; i++) {
|
||||||
|
line = &lr->lines[i];
|
||||||
desc = lr->lines[i].desc;
|
desc = lr->lines[i].desc;
|
||||||
flags = gpio_v2_line_config_flags(lc, i);
|
flags = gpio_v2_line_config_flags(lc, i);
|
||||||
polarity_change =
|
|
||||||
(!!test_bit(FLAG_ACTIVE_LOW, &desc->flags) !=
|
|
||||||
((flags & GPIO_V2_LINE_FLAG_ACTIVE_LOW) != 0));
|
|
||||||
|
|
||||||
prev_hte_flag = !!test_bit(FLAG_EVENT_CLOCK_HTE, &desc->flags);
|
|
||||||
|
|
||||||
gpio_v2_line_config_flags_to_desc_flags(flags, &desc->flags);
|
gpio_v2_line_config_flags_to_desc_flags(flags, &desc->flags);
|
||||||
|
edflags = flags & GPIO_V2_LINE_EDGE_DETECTOR_FLAGS;
|
||||||
/*
|
/*
|
||||||
* Lines have to be requested explicitly for input
|
* Lines have to be requested explicitly for input
|
||||||
* or output, else the line will be treated "as is".
|
* or output, else the line will be treated "as is".
|
||||||
@ -1308,7 +1302,7 @@ static long linereq_set_config_unlocked(struct linereq *lr,
|
|||||||
if (flags & GPIO_V2_LINE_FLAG_OUTPUT) {
|
if (flags & GPIO_V2_LINE_FLAG_OUTPUT) {
|
||||||
int val = gpio_v2_line_config_output_value(lc, i);
|
int val = gpio_v2_line_config_output_value(lc, i);
|
||||||
|
|
||||||
edge_detector_stop(&lr->lines[i], prev_hte_flag);
|
edge_detector_stop(line);
|
||||||
ret = gpiod_direction_output(desc, val);
|
ret = gpiod_direction_output(desc, val);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
@ -1317,12 +1311,13 @@ static long linereq_set_config_unlocked(struct linereq *lr,
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = edge_detector_update(&lr->lines[i], lc, i,
|
ret = edge_detector_update(line, lc, i, edflags);
|
||||||
flags, polarity_change, prev_hte_flag);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WRITE_ONCE(line->edflags, edflags);
|
||||||
|
|
||||||
blocking_notifier_call_chain(&desc->gdev->notifier,
|
blocking_notifier_call_chain(&desc->gdev->notifier,
|
||||||
GPIO_V2_LINE_CHANGED_CONFIG,
|
GPIO_V2_LINE_CHANGED_CONFIG,
|
||||||
desc);
|
desc);
|
||||||
@ -1449,13 +1444,10 @@ static ssize_t linereq_read(struct file *file,
|
|||||||
static void linereq_free(struct linereq *lr)
|
static void linereq_free(struct linereq *lr)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
bool hte;
|
|
||||||
|
|
||||||
for (i = 0; i < lr->num_lines; i++) {
|
for (i = 0; i < lr->num_lines; i++) {
|
||||||
if (lr->lines[i].desc) {
|
if (lr->lines[i].desc) {
|
||||||
hte = !!test_bit(FLAG_EVENT_CLOCK_HTE,
|
edge_detector_stop(&lr->lines[i]);
|
||||||
&lr->lines[i].desc->flags);
|
|
||||||
edge_detector_stop(&lr->lines[i], hte);
|
|
||||||
gpiod_free(lr->lines[i].desc);
|
gpiod_free(lr->lines[i].desc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1491,7 +1483,7 @@ static int linereq_create(struct gpio_device *gdev, void __user *ip)
|
|||||||
struct gpio_v2_line_config *lc;
|
struct gpio_v2_line_config *lc;
|
||||||
struct linereq *lr;
|
struct linereq *lr;
|
||||||
struct file *file;
|
struct file *file;
|
||||||
u64 flags;
|
u64 flags, edflags;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
int fd, ret;
|
int fd, ret;
|
||||||
|
|
||||||
@ -1565,6 +1557,7 @@ static int linereq_create(struct gpio_device *gdev, void __user *ip)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out_free_linereq;
|
goto out_free_linereq;
|
||||||
|
|
||||||
|
edflags = flags & GPIO_V2_LINE_EDGE_DETECTOR_FLAGS;
|
||||||
/*
|
/*
|
||||||
* Lines have to be requested explicitly for input
|
* Lines have to be requested explicitly for input
|
||||||
* or output, else the line will be treated "as is".
|
* or output, else the line will be treated "as is".
|
||||||
@ -1581,12 +1574,13 @@ static int linereq_create(struct gpio_device *gdev, void __user *ip)
|
|||||||
goto out_free_linereq;
|
goto out_free_linereq;
|
||||||
|
|
||||||
ret = edge_detector_setup(&lr->lines[i], lc, i,
|
ret = edge_detector_setup(&lr->lines[i], lc, i,
|
||||||
flags & GPIO_V2_LINE_EDGE_FLAGS,
|
edflags);
|
||||||
flags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_free_linereq;
|
goto out_free_linereq;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lr->lines[i].edflags = edflags;
|
||||||
|
|
||||||
blocking_notifier_call_chain(&desc->gdev->notifier,
|
blocking_notifier_call_chain(&desc->gdev->notifier,
|
||||||
GPIO_V2_LINE_CHANGED_REQUESTED, desc);
|
GPIO_V2_LINE_CHANGED_REQUESTED, desc);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user