summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNuno Sá <nuno.sa@analog.com>2020-04-13 10:24:42 +0200
committerJonathan Cameron <Jonathan.Cameron@huawei.com>2020-04-25 16:10:44 +0100
commitb9c5eec725d67b548e4dfdc406d6ca2c6d30d1c2 (patch)
treeb73655984539cb5c215393087baf730a330073cd
parent698211065d4aa71ce599b38c23452664a5a8e370 (diff)
iio: adis: Add adis_update_bits() APIs
This patch adds a `regmap_update_bits()` like API to the ADIS library. It provides locked and unlocked variant. Signed-off-by: Nuno Sá <nuno.sa@analog.com> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
-rw-r--r--drivers/iio/imu/adis.c25
-rw-r--r--include/linux/iio/imu/adis.h59
2 files changed, 84 insertions, 0 deletions
diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c
index 2e7d0d337f8f..c539dfa3b8d3 100644
--- a/drivers/iio/imu/adis.c
+++ b/drivers/iio/imu/adis.c
@@ -223,6 +223,31 @@ int __adis_read_reg(struct adis *adis, unsigned int reg,
return ret;
}
EXPORT_SYMBOL_GPL(__adis_read_reg);
+/**
+ * __adis_update_bits_base() - ADIS Update bits function - Unlocked version
+ * @adis: The adis device
+ * @reg: The address of the lower of the two registers
+ * @mask: Bitmask to change
+ * @val: Value to be written
+ * @size: Size of the register to update
+ *
+ * Updates the desired bits of @reg in accordance with @mask and @val.
+ */
+int __adis_update_bits_base(struct adis *adis, unsigned int reg, const u32 mask,
+ const u32 val, u8 size)
+{
+ int ret;
+ u32 __val;
+
+ ret = __adis_read_reg(adis, reg, &__val, size);
+ if (ret)
+ return ret;
+
+ __val = (__val & ~mask) | (val & mask);
+
+ return __adis_write_reg(adis, reg, __val, size);
+}
+EXPORT_SYMBOL_GPL(__adis_update_bits_base);
#ifdef CONFIG_DEBUG_FS
diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h
index 70e4d1d262f5..247fc4c7185c 100644
--- a/include/linux/iio/imu/adis.h
+++ b/include/linux/iio/imu/adis.h
@@ -333,6 +333,65 @@ static inline int adis_read_reg_32(struct adis *adis, unsigned int reg,
return ret;
}
+int __adis_update_bits_base(struct adis *adis, unsigned int reg, const u32 mask,
+ const u32 val, u8 size);
+/**
+ * adis_update_bits_base() - ADIS Update bits function - Locked version
+ * @adis: The adis device
+ * @reg: The address of the lower of the two registers
+ * @mask: Bitmask to change
+ * @val: Value to be written
+ * @size: Size of the register to update
+ *
+ * Updates the desired bits of @reg in accordance with @mask and @val.
+ */
+static inline int adis_update_bits_base(struct adis *adis, unsigned int reg,
+ const u32 mask, const u32 val, u8 size)
+{
+ int ret;
+
+ mutex_lock(&adis->state_lock);
+ ret = __adis_update_bits_base(adis, reg, mask, val, size);
+ mutex_unlock(&adis->state_lock);
+ return ret;
+}
+
+/**
+ * adis_update_bits() - Wrapper macro for adis_update_bits_base - Locked version
+ * @adis: The adis device
+ * @reg: The address of the lower of the two registers
+ * @mask: Bitmask to change
+ * @val: Value to be written
+ *
+ * This macro evaluates the sizeof of @val at compile time and calls
+ * adis_update_bits_base() accordingly. Be aware that using MACROS/DEFINES for
+ * @val can lead to undesired behavior if the register to update is 16bit.
+ */
+#define adis_update_bits(adis, reg, mask, val) ({ \
+ BUILD_BUG_ON(sizeof(val) == 1 || sizeof(val) == 8); \
+ __builtin_choose_expr(sizeof(val) == 4, \
+ adis_update_bits_base(adis, reg, mask, val, 4), \
+ adis_update_bits_base(adis, reg, mask, val, 2)); \
+})
+
+/**
+ * adis_update_bits() - Wrapper macro for adis_update_bits_base
+ * @adis: The adis device
+ * @reg: The address of the lower of the two registers
+ * @mask: Bitmask to change
+ * @val: Value to be written
+ *
+ * This macro evaluates the sizeof of @val at compile time and calls
+ * adis_update_bits_base() accordingly. Be aware that using MACROS/DEFINES for
+ * @val can lead to undesired behavior if the register to update is 16bit.
+ */
+#define __adis_update_bits(adis, reg, mask, val) ({ \
+ BUILD_BUG_ON(sizeof(val) == 1 || sizeof(val) == 8); \
+ __builtin_choose_expr(sizeof(val) == 4, \
+ __adis_update_bits_base(adis, reg, mask, val, 4), \
+ __adis_update_bits_base(adis, reg, mask, val, 2)); \
+})
+
int adis_enable_irq(struct adis *adis, bool enable);
int __adis_check_status(struct adis *adis);
int __adis_initial_startup(struct adis *adis);