Skip to content

Commit c971f11

Browse files
committed
Merge tag 'regmap-v6.16' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap
Pull regmap updates from Mark Brown: "This release we have one new feature, support for chips that report edge interrupts but don't provide distinct readback of that status per line, plus a few cleanups" * tag 'regmap-v6.16' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap: regmap: irq: Add support for chips without separate IRQ status regmap-irq: Use dedicated interrupt wake setters regmap: Move selecting for REGMAP_MDIO and REGMAP_IRQ regcache: Use sort()'s default swap() implementation
2 parents aacc73c + 1c12fbd commit c971f11

File tree

4 files changed

+76
-47
lines changed

4 files changed

+76
-47
lines changed

drivers/base/regmap/Kconfig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
config REGMAP
77
bool
88
default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_W1 || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ || REGMAP_SOUNDWIRE || REGMAP_SOUNDWIRE_MBQ || REGMAP_SCCB || REGMAP_I3C || REGMAP_SPI_AVMM || REGMAP_MDIO || REGMAP_FSI)
9-
select IRQ_DOMAIN if REGMAP_IRQ
10-
select MDIO_BUS if REGMAP_MDIO
119
help
1210
Enable support for the Register Map (regmap) access API.
1311

@@ -58,12 +56,14 @@ config REGMAP_W1
5856

5957
config REGMAP_MDIO
6058
tristate
59+
select MDIO_BUS
6160

6261
config REGMAP_MMIO
6362
tristate
6463

6564
config REGMAP_IRQ
6665
bool
66+
select IRQ_DOMAIN
6767

6868
config REGMAP_RAM
6969
tristate

drivers/base/regmap/regcache.c

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,21 +34,10 @@ static int regcache_defaults_cmp(const void *a, const void *b)
3434
return 0;
3535
}
3636

37-
static void regcache_defaults_swap(void *a, void *b, int size)
38-
{
39-
struct reg_default *x = a;
40-
struct reg_default *y = b;
41-
struct reg_default tmp;
42-
43-
tmp = *x;
44-
*x = *y;
45-
*y = tmp;
46-
}
47-
4837
void regcache_sort_defaults(struct reg_default *defaults, unsigned int ndefaults)
4938
{
5039
sort(defaults, ndefaults, sizeof(*defaults),
51-
regcache_defaults_cmp, regcache_defaults_swap);
40+
regcache_defaults_cmp, NULL);
5241
}
5342
EXPORT_SYMBOL_GPL(regcache_sort_defaults);
5443

drivers/base/regmap/regmap-irq.c

Lines changed: 70 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@
66
//
77
// Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
88

9+
#include <linux/array_size.h>
910
#include <linux/device.h>
1011
#include <linux/export.h>
1112
#include <linux/interrupt.h>
1213
#include <linux/irq.h>
1314
#include <linux/irqdomain.h>
15+
#include <linux/overflow.h>
1416
#include <linux/pm_runtime.h>
1517
#include <linux/regmap.h>
1618
#include <linux/slab.h>
@@ -33,6 +35,7 @@ struct regmap_irq_chip_data {
3335
void *status_reg_buf;
3436
unsigned int *main_status_buf;
3537
unsigned int *status_buf;
38+
unsigned int *prev_status_buf;
3639
unsigned int *mask_buf;
3740
unsigned int *mask_buf_def;
3841
unsigned int *wake_buf;
@@ -193,10 +196,10 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
193196
/* If we've changed our wakeup count propagate it to the parent */
194197
if (d->wake_count < 0)
195198
for (i = d->wake_count; i < 0; i++)
196-
irq_set_irq_wake(d->irq, 0);
199+
disable_irq_wake(d->irq);
197200
else if (d->wake_count > 0)
198201
for (i = 0; i < d->wake_count; i++)
199-
irq_set_irq_wake(d->irq, 1);
202+
enable_irq_wake(d->irq);
200203

201204
d->wake_count = 0;
202205

@@ -332,27 +335,13 @@ static inline int read_sub_irq_data(struct regmap_irq_chip_data *data,
332335
return ret;
333336
}
334337

335-
static irqreturn_t regmap_irq_thread(int irq, void *d)
338+
static int read_irq_data(struct regmap_irq_chip_data *data)
336339
{
337-
struct regmap_irq_chip_data *data = d;
338340
const struct regmap_irq_chip *chip = data->chip;
339341
struct regmap *map = data->map;
340342
int ret, i;
341-
bool handled = false;
342343
u32 reg;
343344

344-
if (chip->handle_pre_irq)
345-
chip->handle_pre_irq(chip->irq_drv_data);
346-
347-
if (chip->runtime_pm) {
348-
ret = pm_runtime_get_sync(map->dev);
349-
if (ret < 0) {
350-
dev_err(map->dev, "IRQ thread failed to resume: %d\n",
351-
ret);
352-
goto exit;
353-
}
354-
}
355-
356345
/*
357346
* Read only registers with active IRQs if the chip has 'main status
358347
* register'. Else read in the statuses, using a single bulk read if
@@ -379,10 +368,8 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
379368
reg = data->get_irq_reg(data, chip->main_status, i);
380369
ret = regmap_read(map, reg, &data->main_status_buf[i]);
381370
if (ret) {
382-
dev_err(map->dev,
383-
"Failed to read IRQ status %d\n",
384-
ret);
385-
goto exit;
371+
dev_err(map->dev, "Failed to read IRQ status %d\n", ret);
372+
return ret;
386373
}
387374
}
388375

@@ -398,10 +385,8 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
398385
ret = read_sub_irq_data(data, b);
399386

400387
if (ret != 0) {
401-
dev_err(map->dev,
402-
"Failed to read IRQ status %d\n",
403-
ret);
404-
goto exit;
388+
dev_err(map->dev, "Failed to read IRQ status %d\n", ret);
389+
return ret;
405390
}
406391
}
407392

@@ -418,9 +403,8 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
418403
data->status_reg_buf,
419404
chip->num_regs);
420405
if (ret != 0) {
421-
dev_err(map->dev, "Failed to read IRQ status: %d\n",
422-
ret);
423-
goto exit;
406+
dev_err(map->dev, "Failed to read IRQ status: %d\n", ret);
407+
return ret;
424408
}
425409

426410
for (i = 0; i < data->chip->num_regs; i++) {
@@ -436,7 +420,7 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
436420
break;
437421
default:
438422
BUG();
439-
goto exit;
423+
return -EIO;
440424
}
441425
}
442426

@@ -447,10 +431,8 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
447431
ret = regmap_read(map, reg, &data->status_buf[i]);
448432

449433
if (ret != 0) {
450-
dev_err(map->dev,
451-
"Failed to read IRQ status: %d\n",
452-
ret);
453-
goto exit;
434+
dev_err(map->dev, "Failed to read IRQ status: %d\n", ret);
435+
return ret;
454436
}
455437
}
456438
}
@@ -459,6 +441,42 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
459441
for (i = 0; i < data->chip->num_regs; i++)
460442
data->status_buf[i] = ~data->status_buf[i];
461443

444+
return 0;
445+
}
446+
447+
static irqreturn_t regmap_irq_thread(int irq, void *d)
448+
{
449+
struct regmap_irq_chip_data *data = d;
450+
const struct regmap_irq_chip *chip = data->chip;
451+
struct regmap *map = data->map;
452+
int ret, i;
453+
bool handled = false;
454+
u32 reg;
455+
456+
if (chip->handle_pre_irq)
457+
chip->handle_pre_irq(chip->irq_drv_data);
458+
459+
if (chip->runtime_pm) {
460+
ret = pm_runtime_get_sync(map->dev);
461+
if (ret < 0) {
462+
dev_err(map->dev, "IRQ thread failed to resume: %d\n", ret);
463+
goto exit;
464+
}
465+
}
466+
467+
ret = read_irq_data(data);
468+
if (ret < 0)
469+
goto exit;
470+
471+
if (chip->status_is_level) {
472+
for (i = 0; i < data->chip->num_regs; i++) {
473+
unsigned int val = data->status_buf[i];
474+
475+
data->status_buf[i] ^= data->prev_status_buf[i];
476+
data->prev_status_buf[i] = val;
477+
}
478+
}
479+
462480
/*
463481
* Ignore masked IRQs and ack if we need to; we ack early so
464482
* there is no race between handling and acknowledging the
@@ -705,6 +723,13 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
705723
if (!d->status_buf)
706724
goto err_alloc;
707725

726+
if (chip->status_is_level) {
727+
d->prev_status_buf = kcalloc(chip->num_regs, sizeof(*d->prev_status_buf),
728+
GFP_KERNEL);
729+
if (!d->prev_status_buf)
730+
goto err_alloc;
731+
}
732+
708733
d->mask_buf = kcalloc(chip->num_regs, sizeof(*d->mask_buf),
709734
GFP_KERNEL);
710735
if (!d->mask_buf)
@@ -881,6 +906,16 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
881906
}
882907
}
883908

909+
/* Store current levels */
910+
if (chip->status_is_level) {
911+
ret = read_irq_data(d);
912+
if (ret < 0)
913+
goto err_alloc;
914+
915+
memcpy(d->prev_status_buf, d->status_buf,
916+
array_size(d->chip->num_regs, sizeof(d->prev_status_buf[0])));
917+
}
918+
884919
ret = regmap_irq_create_domain(fwnode, irq_base, chip, d);
885920
if (ret)
886921
goto err_alloc;
@@ -908,6 +943,7 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
908943
kfree(d->mask_buf);
909944
kfree(d->main_status_buf);
910945
kfree(d->status_buf);
946+
kfree(d->prev_status_buf);
911947
kfree(d->status_reg_buf);
912948
if (d->config_buf) {
913949
for (i = 0; i < chip->num_config_bases; i++)
@@ -985,6 +1021,7 @@ void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *d)
9851021
kfree(d->main_status_buf);
9861022
kfree(d->status_reg_buf);
9871023
kfree(d->status_buf);
1024+
kfree(d->prev_status_buf);
9881025
if (d->config_buf) {
9891026
for (i = 0; i < d->chip->num_config_bases; i++)
9901027
kfree(d->config_buf[i]);

include/linux/regmap.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1641,6 +1641,8 @@ struct regmap_irq_chip_data;
16411641
* @ack_invert: Inverted ack register: cleared bits for ack.
16421642
* @clear_ack: Use this to set 1 and 0 or vice-versa to clear interrupts.
16431643
* @status_invert: Inverted status register: cleared bits are active interrupts.
1644+
* @status_is_level: Status register is actuall signal level: Xor status
1645+
* register with previous value to get active interrupts.
16441646
* @wake_invert: Inverted wake register: cleared bits are wake enabled.
16451647
* @type_in_mask: Use the mask registers for controlling irq type. Use this if
16461648
* the hardware provides separate bits for rising/falling edge
@@ -1704,6 +1706,7 @@ struct regmap_irq_chip {
17041706
unsigned int ack_invert:1;
17051707
unsigned int clear_ack:1;
17061708
unsigned int status_invert:1;
1709+
unsigned int status_is_level:1;
17071710
unsigned int wake_invert:1;
17081711
unsigned int type_in_mask:1;
17091712
unsigned int clear_on_unmask:1;

0 commit comments

Comments
 (0)