Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit efeb1a3a authored by Mark Brown's avatar Mark Brown
Browse files

Merge remote-tracking branches 'regmap/topic/bulk', 'regmap/topic/i2c',...

Merge remote-tracking branches 'regmap/topic/bulk', 'regmap/topic/i2c', 'regmap/topic/iopoll', 'regmap/topic/irq' and 'regmap/topic/maintainers' into regmap-next
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -9600,6 +9600,7 @@ M: Mark Brown <broonie@kernel.org>
L:	linux-kernel@vger.kernel.org
T:	git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap.git
S:	Supported
F:	Documentation/devicetree/bindings/regmap/
F:	drivers/base/regmap/
F:	include/linux/regmap.h

+1 −1
Original line number Diff line number Diff line
@@ -259,7 +259,7 @@ static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c,
{
	if (i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C))
		return &regmap_i2c;
	else if (config->reg_bits == 8 &&
	else if (config->val_bits == 8 && config->reg_bits == 8 &&
		 i2c_check_functionality(i2c->adapter,
					 I2C_FUNC_SMBUS_I2C_BLOCK))
		return &regmap_i2c_smbus_i2c_block;
+11 −4
Original line number Diff line number Diff line
@@ -268,13 +268,16 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
	bool handled = false;
	u32 reg;

	if (chip->handle_pre_irq)
		chip->handle_pre_irq(chip->irq_drv_data);

	if (chip->runtime_pm) {
		ret = pm_runtime_get_sync(map->dev);
		if (ret < 0) {
			dev_err(map->dev, "IRQ thread failed to resume: %d\n",
				ret);
			pm_runtime_put(map->dev);
			return IRQ_NONE;
			goto exit;
		}
	}

@@ -296,7 +299,7 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
		if (ret != 0) {
			dev_err(map->dev, "Failed to read IRQ status: %d\n",
				ret);
			return IRQ_NONE;
			goto exit;
		}

		for (i = 0; i < data->chip->num_regs; i++) {
@@ -312,7 +315,7 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
				break;
			default:
				BUG();
				return IRQ_NONE;
				goto exit;
			}
		}

@@ -329,7 +332,7 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
					ret);
				if (chip->runtime_pm)
					pm_runtime_put(map->dev);
				return IRQ_NONE;
				goto exit;
			}
		}
	}
@@ -365,6 +368,10 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
	if (chip->runtime_pm)
		pm_runtime_put(map->dev);

exit:
	if (chip->handle_post_irq)
		chip->handle_post_irq(chip->irq_drv_data);

	if (handled)
		return IRQ_HANDLED;
	else
+28 −3
Original line number Diff line number Diff line
@@ -1777,8 +1777,6 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
	size_t val_bytes = map->format.val_bytes;
	size_t total_size = val_bytes * val_count;

	if (map->bus && !map->format.parse_inplace)
		return -EINVAL;
	if (!IS_ALIGNED(reg, map->reg_stride))
		return -EINVAL;

@@ -1789,7 +1787,8 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
	 *
	 * The first if block is used for memory mapped io. It does not allow
	 * val_bytes of 3 for example.
	 * The second one is used for busses which do not have this limitation
	 * The second one is for busses that do not provide raw I/O.
	 * The third one is used for busses which do not have these limitations
	 * and can write arbitrary value lengths.
	 */
	if (!map->bus) {
@@ -1825,6 +1824,32 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
		}
out:
		map->unlock(map->lock_arg);
	} else if (map->bus && !map->format.parse_inplace) {
		const u8 *u8 = val;
		const u16 *u16 = val;
		const u32 *u32 = val;
		unsigned int ival;

		for (i = 0; i < val_count; i++) {
			switch (map->format.val_bytes) {
			case 4:
				ival = u32[i];
				break;
			case 2:
				ival = u16[i];
				break;
			case 1:
				ival = u8[i];
				break;
			default:
				return -EINVAL;
			}

			ret = regmap_write(map, reg + (i * map->reg_stride),
					   ival);
			if (ret)
				return ret;
		}
	} else if (map->use_single_write ||
		   (map->max_raw_write && map->max_raw_write < total_size)) {
		int chunk_stride = map->reg_stride;
+49 −0
Original line number Diff line number Diff line
@@ -95,6 +95,45 @@ struct reg_sequence {
#define	regmap_fields_force_update_bits(field, id, mask, val) \
	regmap_fields_update_bits_base(field, id, mask, val, NULL, false, true)

/**
 * regmap_read_poll_timeout - Poll until a condition is met or a timeout occurs
 * @map: Regmap to read from
 * @addr: Address to poll
 * @val: Unsigned integer variable to read the value into
 * @cond: Break condition (usually involving @val)
 * @sleep_us: Maximum time to sleep between reads in us (0
 *            tight-loops).  Should be less than ~20ms since usleep_range
 *            is used (see Documentation/timers/timers-howto.txt).
 * @timeout_us: Timeout in us, 0 means never timeout
 *
 * Returns 0 on success and -ETIMEDOUT upon a timeout or the regmap_read
 * error return value in case of a error read. In the two former cases,
 * the last read value at @addr is stored in @val. Must not be called
 * from atomic context if sleep_us or timeout_us are used.
 *
 * This is modelled after the readx_poll_timeout macros in linux/iopoll.h.
 */
#define regmap_read_poll_timeout(map, addr, val, cond, sleep_us, timeout_us) \
({ \
	ktime_t timeout = ktime_add_us(ktime_get(), timeout_us); \
	int ret; \
	might_sleep_if(sleep_us); \
	for (;;) { \
		ret = regmap_read((map), (addr), &(val)); \
		if (ret) \
			break; \
		if (cond) \
			break; \
		if (timeout_us && ktime_compare(ktime_get(), timeout) > 0) { \
			ret = regmap_read((map), (addr), &(val)); \
			break; \
		} \
		if (sleep_us) \
			usleep_range((sleep_us >> 2) + 1, sleep_us); \
	} \
	ret ?: ((cond) ? 0 : -ETIMEDOUT); \
})

#ifdef CONFIG_REGMAP

enum regmap_endian {
@@ -851,6 +890,12 @@ struct regmap_irq {
 * @num_type_reg:    Number of type registers.
 * @type_reg_stride: Stride to use for chips where type registers are not
 *			contiguous.
 * @handle_pre_irq:  Driver specific callback to handle interrupt from device
 *		     before regmap_irq_handler process the interrupts.
 * @handle_post_irq: Driver specific callback to handle interrupt from device
 *		     after handling the interrupts in regmap_irq_handler().
 * @irq_drv_data:    Driver specific IRQ data which is passed as parameter when
 *		     driver specific pre/post interrupt handler is called.
 */
struct regmap_irq_chip {
	const char *name;
@@ -877,6 +922,10 @@ struct regmap_irq_chip {

	int num_type_reg;
	unsigned int type_reg_stride;

	int (*handle_pre_irq)(void *irq_drv_data);
	int (*handle_post_irq)(void *irq_drv_data);
	void *irq_drv_data;
};

struct regmap_irq_chip_data;