aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-11-02 19:16:24 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2015-11-02 19:16:24 -0500
commit5062ecdb662bf3aed6dc975019c53ffcd3b01d1c (patch)
treeb03fcaa4f72617938ccc7c711ccbbc91fb2d98a1 /drivers/base
parente86328c489d7ecdca99410a06a3f448caf7857bf (diff)
parentd4a1a317e7478b70e18b9cc8eac7d29090121b6e (diff)
Merge tag 'regmap-v4.4' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap
Pull regmap updates from Mark Brown: "Quite a few new features for regmap this time, mostly expanding things around the edges of the existing functionality to cover more devices rather than thinsg with wide applicability: - Support for offload of the update_bits() operation to hardware where devices implement bit level access. - Support for a few extra operations that need scratch buffers on fast_io devices where we can't sleep. - Expanded the feature set of regmap_irq to cope with some extra register layouts. - Cleanups to the debugfs code" * tag 'regmap-v4.4' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap: regmap: Allow installing custom reg_update_bits function regmap: debugfs: simplify regmap_reg_ranges_read_file() slightly regmap: debugfs: use memcpy instead of snprintf regmap: debugfs: use snprintf return value in regmap_reg_ranges_read_file() regmap: Add generic macro to define regmap_irq regmap: debugfs: Remove scratch buffer for register length calculation regmap: irq: add ack_invert flag for chips using cleared bits as ack regmap: irq: add support for chips who have separate unmask registers regmap: Allocate buffers with GFP_ATOMIC when fast_io == true
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/regmap/internal.h3
-rw-r--r--drivers/base/regmap/regmap-debugfs.c23
-rw-r--r--drivers/base/regmap/regmap-irq.c43
-rw-r--r--drivers/base/regmap/regmap.c41
4 files changed, 80 insertions, 30 deletions
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index cc557886ab23..3250e53473a3 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -59,6 +59,7 @@ struct regmap {
59 regmap_lock lock; 59 regmap_lock lock;
60 regmap_unlock unlock; 60 regmap_unlock unlock;
61 void *lock_arg; /* This is passed to lock/unlock functions */ 61 void *lock_arg; /* This is passed to lock/unlock functions */
62 gfp_t alloc_flags;
62 63
63 struct device *dev; /* Device we do I/O on */ 64 struct device *dev; /* Device we do I/O on */
64 void *work_buf; /* Scratch buffer used to format I/O */ 65 void *work_buf; /* Scratch buffer used to format I/O */
@@ -98,6 +99,8 @@ struct regmap {
98 99
99 int (*reg_read)(void *context, unsigned int reg, unsigned int *val); 100 int (*reg_read)(void *context, unsigned int reg, unsigned int *val);
100 int (*reg_write)(void *context, unsigned int reg, unsigned int val); 101 int (*reg_write)(void *context, unsigned int reg, unsigned int val);
102 int (*reg_update_bits)(void *context, unsigned int reg,
103 unsigned int mask, unsigned int val);
101 104
102 bool defer_caching; 105 bool defer_caching;
103 106
diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c
index 4c55cfbad19e..3f0a7e262d69 100644
--- a/drivers/base/regmap/regmap-debugfs.c
+++ b/drivers/base/regmap/regmap-debugfs.c
@@ -30,7 +30,7 @@ static LIST_HEAD(regmap_debugfs_early_list);
30static DEFINE_MUTEX(regmap_debugfs_early_lock); 30static DEFINE_MUTEX(regmap_debugfs_early_lock);
31 31
32/* Calculate the length of a fixed format */ 32/* Calculate the length of a fixed format */
33static size_t regmap_calc_reg_len(int max_val, char *buf, size_t buf_size) 33static size_t regmap_calc_reg_len(int max_val)
34{ 34{
35 return snprintf(NULL, 0, "%x", max_val); 35 return snprintf(NULL, 0, "%x", max_val);
36} 36}
@@ -173,8 +173,7 @@ static inline void regmap_calc_tot_len(struct regmap *map,
173{ 173{
174 /* Calculate the length of a fixed format */ 174 /* Calculate the length of a fixed format */
175 if (!map->debugfs_tot_len) { 175 if (!map->debugfs_tot_len) {
176 map->debugfs_reg_len = regmap_calc_reg_len(map->max_register, 176 map->debugfs_reg_len = regmap_calc_reg_len(map->max_register),
177 buf, count);
178 map->debugfs_val_len = 2 * map->format.val_bytes; 177 map->debugfs_val_len = 2 * map->format.val_bytes;
179 map->debugfs_tot_len = map->debugfs_reg_len + 178 map->debugfs_tot_len = map->debugfs_reg_len +
180 map->debugfs_val_len + 3; /* : \n */ 179 map->debugfs_val_len + 3; /* : \n */
@@ -338,6 +337,7 @@ static ssize_t regmap_reg_ranges_read_file(struct file *file,
338 char *buf; 337 char *buf;
339 char *entry; 338 char *entry;
340 int ret; 339 int ret;
340 unsigned entry_len;
341 341
342 if (*ppos < 0 || !count) 342 if (*ppos < 0 || !count)
343 return -EINVAL; 343 return -EINVAL;
@@ -365,18 +365,15 @@ static ssize_t regmap_reg_ranges_read_file(struct file *file,
365 p = 0; 365 p = 0;
366 mutex_lock(&map->cache_lock); 366 mutex_lock(&map->cache_lock);
367 list_for_each_entry(c, &map->debugfs_off_cache, list) { 367 list_for_each_entry(c, &map->debugfs_off_cache, list) {
368 snprintf(entry, PAGE_SIZE, "%x-%x", 368 entry_len = snprintf(entry, PAGE_SIZE, "%x-%x\n",
369 c->base_reg, c->max_reg); 369 c->base_reg, c->max_reg);
370 if (p >= *ppos) { 370 if (p >= *ppos) {
371 if (buf_pos + 1 + strlen(entry) > count) 371 if (buf_pos + entry_len > count)
372 break; 372 break;
373 snprintf(buf + buf_pos, count - buf_pos, 373 memcpy(buf + buf_pos, entry, entry_len);
374 "%s", entry); 374 buf_pos += entry_len;
375 buf_pos += strlen(entry);
376 buf[buf_pos] = '\n';
377 buf_pos++;
378 } 375 }
379 p += strlen(entry) + 1; 376 p += entry_len;
380 } 377 }
381 mutex_unlock(&map->cache_lock); 378 mutex_unlock(&map->cache_lock);
382 379
@@ -420,7 +417,7 @@ static ssize_t regmap_access_read_file(struct file *file,
420 return -ENOMEM; 417 return -ENOMEM;
421 418
422 /* Calculate the length of a fixed format */ 419 /* Calculate the length of a fixed format */
423 reg_len = regmap_calc_reg_len(map->max_register, buf, count); 420 reg_len = regmap_calc_reg_len(map->max_register);
424 tot_len = reg_len + 10; /* ': R W V P\n' */ 421 tot_len = reg_len + 10; /* ': R W V P\n' */
425 422
426 for (i = 0; i <= map->max_register; i += map->reg_stride) { 423 for (i = 0; i <= map->max_register; i += map->reg_stride) {
diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c
index 38d1f72d869c..8d16db533527 100644
--- a/drivers/base/regmap/regmap-irq.c
+++ b/drivers/base/regmap/regmap-irq.c
@@ -63,6 +63,7 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
63 struct regmap *map = d->map; 63 struct regmap *map = d->map;
64 int i, ret; 64 int i, ret;
65 u32 reg; 65 u32 reg;
66 u32 unmask_offset;
66 67
67 if (d->chip->runtime_pm) { 68 if (d->chip->runtime_pm) {
68 ret = pm_runtime_get_sync(map->dev); 69 ret = pm_runtime_get_sync(map->dev);
@@ -79,12 +80,28 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
79 for (i = 0; i < d->chip->num_regs; i++) { 80 for (i = 0; i < d->chip->num_regs; i++) {
80 reg = d->chip->mask_base + 81 reg = d->chip->mask_base +
81 (i * map->reg_stride * d->irq_reg_stride); 82 (i * map->reg_stride * d->irq_reg_stride);
82 if (d->chip->mask_invert) 83 if (d->chip->mask_invert) {
83 ret = regmap_update_bits(d->map, reg, 84 ret = regmap_update_bits(d->map, reg,
84 d->mask_buf_def[i], ~d->mask_buf[i]); 85 d->mask_buf_def[i], ~d->mask_buf[i]);
85 else 86 } else if (d->chip->unmask_base) {
87 /* set mask with mask_base register */
88 ret = regmap_update_bits(d->map, reg,
89 d->mask_buf_def[i], ~d->mask_buf[i]);
90 if (ret < 0)
91 dev_err(d->map->dev,
92 "Failed to sync unmasks in %x\n",
93 reg);
94 unmask_offset = d->chip->unmask_base -
95 d->chip->mask_base;
96 /* clear mask with unmask_base register */
97 ret = regmap_update_bits(d->map,
98 reg + unmask_offset,
99 d->mask_buf_def[i],
100 d->mask_buf[i]);
101 } else {
86 ret = regmap_update_bits(d->map, reg, 102 ret = regmap_update_bits(d->map, reg,
87 d->mask_buf_def[i], d->mask_buf[i]); 103 d->mask_buf_def[i], d->mask_buf[i]);
104 }
88 if (ret != 0) 105 if (ret != 0)
89 dev_err(d->map->dev, "Failed to sync masks in %x\n", 106 dev_err(d->map->dev, "Failed to sync masks in %x\n",
90 reg); 107 reg);
@@ -116,7 +133,11 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
116 if (d->mask_buf[i] && (d->chip->ack_base || d->chip->use_ack)) { 133 if (d->mask_buf[i] && (d->chip->ack_base || d->chip->use_ack)) {
117 reg = d->chip->ack_base + 134 reg = d->chip->ack_base +
118 (i * map->reg_stride * d->irq_reg_stride); 135 (i * map->reg_stride * d->irq_reg_stride);
119 ret = regmap_write(map, reg, d->mask_buf[i]); 136 /* some chips ack by write 0 */
137 if (d->chip->ack_invert)
138 ret = regmap_write(map, reg, ~d->mask_buf[i]);
139 else
140 ret = regmap_write(map, reg, d->mask_buf[i]);
120 if (ret != 0) 141 if (ret != 0)
121 dev_err(d->map->dev, "Failed to ack 0x%x: %d\n", 142 dev_err(d->map->dev, "Failed to ack 0x%x: %d\n",
122 reg, ret); 143 reg, ret);
@@ -339,6 +360,7 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
339 int i; 360 int i;
340 int ret = -ENOMEM; 361 int ret = -ENOMEM;
341 u32 reg; 362 u32 reg;
363 u32 unmask_offset;
342 364
343 if (chip->num_regs <= 0) 365 if (chip->num_regs <= 0)
344 return -EINVAL; 366 return -EINVAL;
@@ -420,7 +442,14 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
420 if (chip->mask_invert) 442 if (chip->mask_invert)
421 ret = regmap_update_bits(map, reg, 443 ret = regmap_update_bits(map, reg,
422 d->mask_buf[i], ~d->mask_buf[i]); 444 d->mask_buf[i], ~d->mask_buf[i]);
423 else 445 else if (d->chip->unmask_base) {
446 unmask_offset = d->chip->unmask_base -
447 d->chip->mask_base;
448 ret = regmap_update_bits(d->map,
449 reg + unmask_offset,
450 d->mask_buf[i],
451 d->mask_buf[i]);
452 } else
424 ret = regmap_update_bits(map, reg, 453 ret = regmap_update_bits(map, reg,
425 d->mask_buf[i], d->mask_buf[i]); 454 d->mask_buf[i], d->mask_buf[i]);
426 if (ret != 0) { 455 if (ret != 0) {
@@ -445,7 +474,11 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
445 if (d->status_buf[i] && (chip->ack_base || chip->use_ack)) { 474 if (d->status_buf[i] && (chip->ack_base || chip->use_ack)) {
446 reg = chip->ack_base + 475 reg = chip->ack_base +
447 (i * map->reg_stride * d->irq_reg_stride); 476 (i * map->reg_stride * d->irq_reg_stride);
448 ret = regmap_write(map, reg, 477 if (chip->ack_invert)
478 ret = regmap_write(map, reg,
479 ~(d->status_buf[i] & d->mask_buf[i]));
480 else
481 ret = regmap_write(map, reg,
449 d->status_buf[i] & d->mask_buf[i]); 482 d->status_buf[i] & d->mask_buf[i]);
450 if (ret != 0) { 483 if (ret != 0) {
451 dev_err(map->dev, "Failed to ack 0x%x: %d\n", 484 dev_err(map->dev, "Failed to ack 0x%x: %d\n",
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index afaf56200674..4ac63c0e50c7 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -561,6 +561,16 @@ struct regmap *__regmap_init(struct device *dev,
561 } 561 }
562 map->lock_arg = map; 562 map->lock_arg = map;
563 } 563 }
564
565 /*
566 * When we write in fast-paths with regmap_bulk_write() don't allocate
567 * scratch buffers with sleeping allocations.
568 */
569 if ((bus && bus->fast_io) || config->fast_io)
570 map->alloc_flags = GFP_ATOMIC;
571 else
572 map->alloc_flags = GFP_KERNEL;
573
564 map->format.reg_bytes = DIV_ROUND_UP(config->reg_bits, 8); 574 map->format.reg_bytes = DIV_ROUND_UP(config->reg_bits, 8);
565 map->format.pad_bytes = config->pad_bits / 8; 575 map->format.pad_bytes = config->pad_bits / 8;
566 map->format.val_bytes = DIV_ROUND_UP(config->val_bits, 8); 576 map->format.val_bytes = DIV_ROUND_UP(config->val_bits, 8);
@@ -619,6 +629,7 @@ struct regmap *__regmap_init(struct device *dev,
619 goto skip_format_initialization; 629 goto skip_format_initialization;
620 } else { 630 } else {
621 map->reg_read = _regmap_bus_read; 631 map->reg_read = _regmap_bus_read;
632 map->reg_update_bits = bus->reg_update_bits;
622 } 633 }
623 634
624 reg_endian = regmap_get_reg_endian(bus, config); 635 reg_endian = regmap_get_reg_endian(bus, config);
@@ -1786,7 +1797,7 @@ out:
1786 if (!val_count) 1797 if (!val_count)
1787 return -EINVAL; 1798 return -EINVAL;
1788 1799
1789 wval = kmemdup(val, val_count * val_bytes, GFP_KERNEL); 1800 wval = kmemdup(val, val_count * val_bytes, map->alloc_flags);
1790 if (!wval) { 1801 if (!wval) {
1791 dev_err(map->dev, "Error in memory allocation\n"); 1802 dev_err(map->dev, "Error in memory allocation\n");
1792 return -ENOMEM; 1803 return -ENOMEM;
@@ -2509,20 +2520,26 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg,
2509 int ret; 2520 int ret;
2510 unsigned int tmp, orig; 2521 unsigned int tmp, orig;
2511 2522
2512 ret = _regmap_read(map, reg, &orig); 2523 if (change)
2513 if (ret != 0) 2524 *change = false;
2514 return ret;
2515 2525
2516 tmp = orig & ~mask; 2526 if (regmap_volatile(map, reg) && map->reg_update_bits) {
2517 tmp |= val & mask; 2527 ret = map->reg_update_bits(map->bus_context, reg, mask, val);
2518 2528 if (ret == 0 && change)
2519 if (force_write || (tmp != orig)) {
2520 ret = _regmap_write(map, reg, tmp);
2521 if (change)
2522 *change = true; 2529 *change = true;
2523 } else { 2530 } else {
2524 if (change) 2531 ret = _regmap_read(map, reg, &orig);
2525 *change = false; 2532 if (ret != 0)
2533 return ret;
2534
2535 tmp = orig & ~mask;
2536 tmp |= val & mask;
2537
2538 if (force_write || (tmp != orig)) {
2539 ret = _regmap_write(map, reg, tmp);
2540 if (ret == 0 && change)
2541 *change = true;
2542 }
2526 } 2543 }
2527 2544
2528 return ret; 2545 return ret;