Hi,
this series was created to add SPI support to the bmc150 accelerometer driver.
To not add any regressions, I had to add some infrastructure that allows to use
regmap with busses that do limit the size of transfers (block smbus). I hope
this is sufficient to not break anything.
The series has several different parts for regmap and the iio driver:
Patches 1-4 fix some minor things in the regmap core code.
Patches 5-11 fix some issues with regmap busses that do not have an
implementation of read() or write(). Currently a lot of the regmap API
functions simply fail for those busses.
Patches 12-14 introduce 'max_raw_io' for busses which defines the max number of
bytes that may be send or received by this bus. This includes handling in
regmap_bulk_read/write and reporting an error for raw_read/writes that are
above this limit (E2BIG).
Patch 15 makes use of max_raw_io by adding smbus i2c block bus driver. This
patch is created to avoid regressions in the bmc150 driver.
Patches 16-20 move bmc150 to use regmap and add SPI support.
As I don't have a bmc150 connected via smbus I am not able to test Patch 14 and
the resulting I2C part of the bmc150 driver. It would be great if someone with
the hardware could test it. Also it would be great to have some test coverage
for all other regmap setups.
Best Regards,
Markus
Markus Pargmann (20):
regmap: Add missing comments about struct regmap_bus
regmap: Remove regmap_bulk_write 64bit support
regmap: Fix integertypes for register address and value
regmap: Do not skip format initialization
regmap: Restructure writes in _regmap_raw_write()
regmap: Fix regmap_bulk_write for bus writes
regmap: Without bus read() or write(), force use_single_rw
regmap: Fix regmap_can_raw_write check
regmap: _regmap_raw_write fix for busses without write()
regmap: _regmap_raw_multi_reg_write: Add reg_write() support
regmap: _regmap_raw_read: Add handling of busses without bus->read()
regmap: Introduce max_raw_io for regmap_bulk_read/write
regmap: regmap max_raw_io getter function
regmap: Add raw_write/read checks for max_raw_write/read sizes
regmap-i2c: Add smbus i2c block support
iio: bmc150: Fix irq checks
iio: bmc150: Use i2c regmap
iio: bcm150: Remove i2c_client from private data
iio: bmc150: Split the driver into core and i2c
iio: bmc150: Add SPI driver
drivers/base/regmap/internal.h | 3 +
drivers/base/regmap/regmap-i2c.c | 46 +++
drivers/base/regmap/regmap.c | 221 ++++++++---
drivers/iio/accel/Kconfig | 32 +-
drivers/iio/accel/Makefile | 4 +-
.../accel/{bmc150-accel.c => bmc150-accel-core.c} | 404 ++++++++-------------
drivers/iio/accel/bmc150-accel-i2c.c | 101 ++++++
drivers/iio/accel/bmc150-accel-spi.c | 86 +++++
drivers/iio/accel/bmc150-accel.h | 21 ++
include/linux/regmap.h | 8 +-
10 files changed, 622 insertions(+), 304 deletions(-)
rename drivers/iio/accel/{bmc150-accel.c => bmc150-accel-core.c} (82%)
create mode 100644 drivers/iio/accel/bmc150-accel-i2c.c
create mode 100644 drivers/iio/accel/bmc150-accel-spi.c
create mode 100644 drivers/iio/accel/bmc150-accel.h
--
2.4.6
There are some fields of this struct undocumented or old. This patch
updates the missing comments.
Signed-off-by: Markus Pargmann <[email protected]>
---
include/linux/regmap.h | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index 59c55ea0f0b5..6ff83c9ddb45 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -296,8 +296,11 @@ typedef void (*regmap_hw_free_context)(void *context);
* if not implemented on a given device.
* @async_write: Write operation which completes asynchronously, optional and
* must serialise with respect to non-async I/O.
+ * @reg_write: Write operation for a register. Writes value to register.
* @read: Read operation. Data is returned in the buffer used to transmit
* data.
+ * @reg_read: Read operation for a register. Reads a value from a register.
+ * @free_conetext: Free context.
* @async_alloc: Allocate a regmap_async() structure.
* @read_flag_mask: Mask to be set in the top byte of the register when doing
* a read.
@@ -307,7 +310,6 @@ typedef void (*regmap_hw_free_context)(void *context);
* @val_format_endian_default: Default endianness for formatted register
* values. Used when the regmap_config specifies DEFAULT. If this is
* DEFAULT, BIG is assumed.
- * @async_size: Size of struct used for async work.
*/
struct regmap_bus {
bool fast_io;
--
2.4.6
Regmap does not support 64bit. The ival that is used to write the 64bit
data to, is unsigned int and can't hold 64bit. _regmap_write also just
supports unsigend int.
This patch removes the 64bit case as it may lead to compile warnings.
Cc: Stephen Boyd <[email protected]>
Signed-off-by: Markus Pargmann <[email protected]>
---
drivers/base/regmap/regmap.c | 5 -----
1 file changed, 5 deletions(-)
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 7111d04f2621..64a106af174f 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -1694,11 +1694,6 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
case 4:
ival = *(u32 *)(val + (i * val_bytes));
break;
-#ifdef CONFIG_64BIT
- case 8:
- ival = *(u64 *)(val + (i * val_bytes));
- break;
-#endif
default:
ret = -EINVAL;
goto out;
--
2.4.6
These values are defined as unsigned int in the struct and are assigned
to int values.
This patch fixes the type to be unsigned int instead.
Signed-off-by: Markus Pargmann <[email protected]>
---
drivers/base/regmap/regmap.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 64a106af174f..4fe5f63edb54 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -1763,8 +1763,8 @@ static int _regmap_raw_multi_reg_write(struct regmap *map,
u8 = buf;
for (i = 0; i < num_regs; i++) {
- int reg = regs[i].reg;
- int val = regs[i].def;
+ unsigned int reg = regs[i].reg;
+ unsigned int val = regs[i].def;
trace_regmap_hw_write_start(map, reg, 1);
map->format.format_reg(u8, reg, map->reg_shift);
u8 += reg_bytes + pad_bytes;
--
2.4.6
It is not obvious why format initialization is skipped here. format
functions are used for example in regmap_bulk_read even if bus is not
set. So they are used even if skipped here which leads to null pointer
errors.
This patch adds format initialization for !bus and !bus->read/write.
Signed-off-by: Markus Pargmann <[email protected]>
---
drivers/base/regmap/regmap.c | 4 ----
1 file changed, 4 deletions(-)
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 4fe5f63edb54..86e94be3c749 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -607,13 +607,11 @@ struct regmap *regmap_init(struct device *dev,
map->reg_write = config->reg_write;
map->defer_caching = false;
- goto skip_format_initialization;
} else if (!bus->read || !bus->write) {
map->reg_read = _regmap_bus_reg_read;
map->reg_write = _regmap_bus_reg_write;
map->defer_caching = false;
- goto skip_format_initialization;
} else {
map->reg_read = _regmap_bus_read;
}
@@ -784,8 +782,6 @@ struct regmap *regmap_init(struct device *dev,
map->reg_write = _regmap_bus_raw_write;
}
-skip_format_initialization:
-
map->range_tree = RB_ROOT;
for (i = 0; i < config->num_ranges; i++) {
const struct regmap_range_cfg *range_cfg = &config->ranges[i];
--
2.4.6
Currently we try to write the data without copying directly using
bus->write() or bus->gather_write() if it exists. If one of the previous
tries to write reported -ENOTSUPP or none of them were usable, we copy
the data into a buffer and use bus->write().
However it does not make sense to try bus->write() a second time with a
copied buffer if it didn't work the first time.
This patch restructures this if/else block to make it clear that this is
not intended for the case where bus->write() returns -ENOTSUPP.
Signed-off-by: Markus Pargmann <[email protected]>
---
drivers/base/regmap/regmap.c | 40 ++++++++++++++++++++++------------------
1 file changed, 22 insertions(+), 18 deletions(-)
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 86e94be3c749..f6bd3517a472 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -1340,30 +1340,34 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
* send the work_buf directly, otherwise try to do a gather
* write.
*/
- if (val == work_val)
+ if (val == work_val) {
ret = map->bus->write(map->bus_context, map->work_buf,
map->format.reg_bytes +
map->format.pad_bytes +
val_len);
- else if (map->bus->gather_write)
- ret = map->bus->gather_write(map->bus_context, map->work_buf,
- map->format.reg_bytes +
- map->format.pad_bytes,
- val, val_len);
-
- /* If that didn't work fall back on linearising by hand. */
- if (ret == -ENOTSUPP) {
- len = map->format.reg_bytes + map->format.pad_bytes + val_len;
- buf = kzalloc(len, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
+ } else {
+ if (map->bus->gather_write)
+ ret = map->bus->gather_write(map->bus_context,
+ map->work_buf,
+ map->format.reg_bytes +
+ map->format.pad_bytes,
+ val, val_len);
+
+ /* If that didn't work fall back on linearising by hand. */
+ if (ret == -ENOTSUPP) {
+ len = map->format.reg_bytes + map->format.pad_bytes +
+ val_len;
+ buf = kzalloc(len, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
- memcpy(buf, map->work_buf, map->format.reg_bytes);
- memcpy(buf + map->format.reg_bytes + map->format.pad_bytes,
- val, val_len);
- ret = map->bus->write(map->bus_context, buf, len);
+ memcpy(buf, map->work_buf, map->format.reg_bytes);
+ memcpy(buf + map->format.reg_bytes +
+ map->format.pad_bytes, val, val_len);
+ ret = map->bus->write(map->bus_context, buf, len);
- kfree(buf);
+ kfree(buf);
+ }
}
trace_regmap_hw_write_done(map, reg, val_len / map->format.val_bytes);
--
2.4.6
The regmap config does not prohibit val_bytes that are not powers of
two. But the current code of regmap_bulk_write for use_single_rw does
limit the possible val_bytes to 1, 2 and 4.
This patch fixes the behaviour to allow bus writes with non-standard
val_bytes sizes.
Cc: Stephen Boyd <[email protected]>
Signed-off-by: Markus Pargmann <[email protected]>
---
drivers/base/regmap/regmap.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index f6bd3517a472..f98bd5bf5c62 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -1680,6 +1680,9 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
* them we have a series of single write operations.
*/
if (!map->bus || map->use_single_rw) {
+ if (val_bytes != 1 && val_bytes != 2 && val_bytes != 4)
+ return -EINVAL;
+
map->lock(map->lock_arg);
for (i = 0; i < val_count; i++) {
unsigned int ival;
@@ -1706,6 +1709,21 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
}
out:
map->unlock(map->lock_arg);
+ } else if (map->use_single_rw) {
+ /*
+ * We need to handle bus writes separate to support val_bytes
+ * that are not powers of 2.
+ */
+ map->lock(map->lock_arg);
+ for (i = 0; i < val_count; i++) {
+ ret = _regmap_raw_write(map,
+ reg + (i * map->reg_stride),
+ val + (i * val_bytes),
+ val_bytes);
+ if (ret)
+ break;
+ }
+ map->unlock(map->lock_arg);
} else {
void *wval;
--
2.4.6
The implementation of regmap bus read() and write() methods are
optional. Therefore we have to handle busses which do not have these
functions. If raw read() and write() is not supported we have to use
reg_read and reg_write always.
This patch sets use_single_rw if read() or write() is not set.
Signed-off-by: Markus Pargmann <[email protected]>
---
drivers/base/regmap/regmap.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index f98bd5bf5c62..35ad3783da70 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -573,7 +573,7 @@ struct regmap *regmap_init(struct device *dev,
map->reg_stride = config->reg_stride;
else
map->reg_stride = 1;
- map->use_single_rw = config->use_single_rw;
+ map->use_single_rw = config->use_single_rw || !bus->read || !bus->write;
map->can_multi_write = config->can_multi_write;
map->dev = dev;
map->bus = bus;
--
2.4.6
This function is missing a check if map->bus->write is implemented. If
it is not implemented arbitrary raw writes are not possible.
Signed-off-by: Markus Pargmann <[email protected]>
---
drivers/base/regmap/regmap.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 35ad3783da70..510dab052a95 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -1382,7 +1382,8 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
*/
bool regmap_can_raw_write(struct regmap *map)
{
- return map->bus && map->format.format_val && map->format.format_reg;
+ return map->bus && map->bus->write && map->format.format_val &&
+ map->format.format_reg;
}
EXPORT_SYMBOL_GPL(regmap_can_raw_write);
--
2.4.6
Some busses don't have a write() function defined. However we can use
reg_write() in special cases.
This patch adds support for reg_write() and throws errors if it was
unsuccessful.
Signed-off-by: Markus Pargmann <[email protected]>
---
drivers/base/regmap/regmap.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 510dab052a95..78eb96288a68 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -1229,6 +1229,11 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
}
}
+ if (!map->bus->write && val_len == map->format.val_bytes) {
+ ret = _regmap_bus_reg_write(map, reg, *(unsigned int *)val);
+ return ret;
+ }
+
range = _regmap_range_lookup(map, reg);
if (range) {
int val_num = val_len / map->format.val_bytes;
@@ -1340,7 +1345,7 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
* send the work_buf directly, otherwise try to do a gather
* write.
*/
- if (val == work_val) {
+ if (val == work_val && map->bus->write) {
ret = map->bus->write(map->bus_context, map->work_buf,
map->format.reg_bytes +
map->format.pad_bytes +
@@ -1354,7 +1359,7 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
val, val_len);
/* If that didn't work fall back on linearising by hand. */
- if (ret == -ENOTSUPP) {
+ if (ret == -ENOTSUPP && map->bus->write) {
len = map->format.reg_bytes + map->format.pad_bytes +
val_len;
buf = kzalloc(len, GFP_KERNEL);
--
2.4.6
Define a fallback for busses which do not define a write() function.
Instead we write one register at a time using reg_write().
Without this patch, _regmap_raw_multi_reg_write would break as it tries
to call bus->write() without checking if it exists before.
Signed-off-by: Markus Pargmann <[email protected]>
---
drivers/base/regmap/regmap.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 78eb96288a68..87f15fb60bc5 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -1778,6 +1778,20 @@ static int _regmap_raw_multi_reg_write(struct regmap *map,
if (!len)
return -EINVAL;
+ /*
+ * If bus->write is not supported we have to use reg_write for each
+ * register value.
+ */
+ if (!map->bus->write) {
+ for (i = 0; i < num_regs; i++) {
+ ret = map->reg_write(map, regs[i].reg, regs[i].def);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+ }
+
buf = kzalloc(len, GFP_KERNEL);
if (!buf)
return -ENOMEM;
--
2.4.6
Handle easy reads by using bus->reg_read(). Return with an error value
if a read is requested that can not be handled with reg_read().
Signed-off-by: Markus Pargmann <[email protected]>
---
drivers/base/regmap/regmap.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 87f15fb60bc5..3b663350c573 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -2071,6 +2071,21 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
WARN_ON(!map->bus);
+ /*
+ * There are busses that do not have a read function as it is optional.
+ * Use their reg_read function instead if the requested number of bytes
+ * is correct.
+ */
+ if (!map->bus->read) {
+ /*
+ * bus_reg_read() does not support reading values that are not
+ * exactly the size of format.val_bytes
+ */
+ if (val_len != map->format.val_bytes)
+ return -EINVAL;
+ return _regmap_bus_reg_read(map, reg, val);
+ }
+
range = _regmap_range_lookup(map, reg);
if (range) {
ret = _regmap_select_page(map, ®, range,
--
2.4.6
There are some busses which have a limit on the maximum number of bytes
that can be send/received. An example for this is
I2C_FUNC_SMBUS_I2C_BLOCK which does not support any reads/writes of more
than 32 bytes. The regmap_bulk operations should still be able to
utilize the full 32 bytes.
Signed-off-by: Markus Pargmann <[email protected]>
---
drivers/base/regmap/internal.h | 3 ++
drivers/base/regmap/regmap.c | 82 ++++++++++++++++++++++++++++++++----------
include/linux/regmap.h | 2 ++
3 files changed, 69 insertions(+), 18 deletions(-)
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index b2b2849fc6d3..f94041658397 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -144,6 +144,9 @@ struct regmap {
/* if set, the device supports multi write mode */
bool can_multi_write;
+ /* if set, raw reads/writes are limited to this size */
+ size_t max_raw_io;
+
struct rb_root range_tree;
void *selector_work_buf; /* Scratch buffer used for selector */
};
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 3b663350c573..6ad4ca849055 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -574,6 +574,7 @@ struct regmap *regmap_init(struct device *dev,
else
map->reg_stride = 1;
map->use_single_rw = config->use_single_rw || !bus->read || !bus->write;
+ map->max_raw_io = bus->max_raw_io;
map->can_multi_write = config->can_multi_write;
map->dev = dev;
map->bus = bus;
@@ -1675,6 +1676,7 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
{
int ret = 0, i;
size_t val_bytes = map->format.val_bytes;
+ size_t total_bytes = val_bytes * val_count;
if (map->bus && !map->format.parse_inplace)
return -EINVAL;
@@ -1715,20 +1717,39 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
}
out:
map->unlock(map->lock_arg);
- } else if (map->use_single_rw) {
+ } else if (map->use_single_rw ||
+ (map->max_raw_io && map->max_raw_io < total_bytes)) {
/*
* We need to handle bus writes separate to support val_bytes
* that are not powers of 2.
*/
+ int reg_stride = map->reg_stride;
+ size_t write_bytes = val_bytes;
+ size_t write_count = val_count;
+
+ if (!map->use_single_rw) {
+ write_count = total_bytes / map->max_raw_io;
+ write_bytes = map->max_raw_io;
+ reg_stride *= write_bytes / val_bytes;
+ }
+
map->lock(map->lock_arg);
+ /* Write as many bytes as possible with maximum write size */
for (i = 0; i < val_count; i++) {
ret = _regmap_raw_write(map,
- reg + (i * map->reg_stride),
- val + (i * val_bytes),
- val_bytes);
+ reg + (i * reg_stride),
+ val + (i * write_bytes),
+ write_bytes);
if (ret)
break;
}
+
+ /* Write remaining bytes */
+ if (!ret && write_bytes * i < total_bytes) {
+ ret = _regmap_raw_write(map, reg + (i * reg_stride),
+ val + (i * write_bytes),
+ total_bytes - i * write_bytes);
+ }
map->unlock(map->lock_arg);
} else {
void *wval;
@@ -2336,24 +2357,49 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
return -EINVAL;
if (map->bus && map->format.parse_inplace && (vol || map->cache_type == REGCACHE_NONE)) {
- /*
- * Some devices does not support bulk read, for
- * them we have a series of single read operations.
- */
- if (map->use_single_rw) {
- for (i = 0; i < val_count; i++) {
- ret = regmap_raw_read(map,
- reg + (i * map->reg_stride),
- val + (i * val_bytes),
- val_bytes);
- if (ret != 0)
- return ret;
- }
- } else {
+ size_t total_size = val_bytes * val_count;
+
+ if (!map->use_single_rw &&
+ (!map->max_raw_io || map->max_raw_io > total_size)) {
ret = regmap_raw_read(map, reg, val,
val_bytes * val_count);
if (ret != 0)
return ret;
+ } else {
+ /*
+ * Some devices do not support bulk read or do not
+ * support large bulk reads, for them we have a series
+ * of read operations.
+ */
+ int reg_stride = map->reg_stride;
+ size_t read_bytes = val_bytes;
+ size_t read_count = val_count;
+
+ if (!map->use_single_rw) {
+ read_count = total_size / map->max_raw_io;
+ read_bytes = map->max_raw_io;
+ reg_stride *= read_bytes / val_bytes;
+ }
+
+ /* Read bytes that fit into the max_raw_io size */
+ for (i = 0; i < read_count; i++) {
+ ret = regmap_raw_read(map,
+ reg + (i * reg_stride),
+ val + (i * read_bytes),
+ read_bytes);
+ if (ret != 0)
+ return ret;
+ }
+
+ /* Read remaining bytes */
+ if (read_bytes * i < total_size) {
+ ret = regmap_raw_read(map,
+ reg + (i * reg_stride),
+ val + (i * read_bytes),
+ total_size - i * read_bytes);
+ if (ret != 0)
+ return ret;
+ }
}
for (i = 0; i < val_count * val_bytes; i += val_bytes)
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index 6ff83c9ddb45..2cb62d141761 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -310,6 +310,7 @@ typedef void (*regmap_hw_free_context)(void *context);
* @val_format_endian_default: Default endianness for formatted register
* values. Used when the regmap_config specifies DEFAULT. If this is
* DEFAULT, BIG is assumed.
+ * @max_raw_io: Max raw read/write size that can be used on the bus.
*/
struct regmap_bus {
bool fast_io;
@@ -324,6 +325,7 @@ struct regmap_bus {
u8 read_flag_mask;
enum regmap_endian reg_format_endian_default;
enum regmap_endian val_format_endian_default;
+ size_t max_raw_io;
};
struct regmap *regmap_init(struct device *dev,
--
2.4.6
Signed-off-by: Markus Pargmann <[email protected]>
---
drivers/base/regmap/regmap.c | 22 ++++++++++++++++++++++
include/linux/regmap.h | 2 ++
2 files changed, 24 insertions(+)
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 6ad4ca849055..8c2be516a100 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -1393,6 +1393,28 @@ bool regmap_can_raw_write(struct regmap *map)
}
EXPORT_SYMBOL_GPL(regmap_can_raw_write);
+/**
+ * regmap_get_raw_io_max - Get the maximum size we can read/write
+ *
+ * @map: Map to check.
+ */
+size_t regmap_get_raw_io_max(struct regmap *map)
+{
+ return map->max_raw_io;
+}
+EXPORT_SYMBOL_GPL(regmap_get_raw_io_max);
+
+/**
+ * regmap_get_raw_read_max - Get the maximum size we can read
+ *
+ * @map: Map to check.
+ */
+size_t regmap_get_raw_read_max(struct regmap *map)
+{
+ return map->max_raw_io;
+}
+EXPORT_SYMBOL_GPL(regmap_get_raw_read_max);
+
static int _regmap_bus_formatted_write(void *context, unsigned int reg,
unsigned int val)
{
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index 2cb62d141761..b236f884f642 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -441,6 +441,8 @@ int regmap_get_max_register(struct regmap *map);
int regmap_get_reg_stride(struct regmap *map);
int regmap_async_complete(struct regmap *map);
bool regmap_can_raw_write(struct regmap *map);
+size_t regmap_get_raw_write_max(struct regmap *map);
+size_t regmap_get_raw_io_max(struct regmap *map);
int regcache_sync(struct regmap *map);
int regcache_sync_region(struct regmap *map, unsigned int min,
--
2.4.6
Check in regmap_raw_read() and regmap_raw_write() for correct maximum
sizes of the operations. Return -E2BIG if this size is not supported
because it is too big.
Also this patch causes an uninitialized variable warning so it
initializes ret (although not necessary).
Signed-off-by: Markus Pargmann <[email protected]>
---
drivers/base/regmap/regmap.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 8c2be516a100..6b636e2ee111 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -1584,6 +1584,8 @@ int regmap_raw_write(struct regmap *map, unsigned int reg,
return -EINVAL;
if (val_len % map->format.val_bytes)
return -EINVAL;
+ if (map->max_raw_io && map->max_raw_io > val_len)
+ return -E2BIG;
map->lock(map->lock_arg);
@@ -2262,7 +2264,8 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
size_t val_bytes = map->format.val_bytes;
size_t val_count = val_len / val_bytes;
unsigned int v;
- int ret, i;
+ int ret = 0;
+ int i;
if (!map->bus)
return -EINVAL;
@@ -2273,8 +2276,14 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
map->lock(map->lock_arg);
- if (regmap_volatile_range(map, reg, val_count) || map->cache_bypass ||
- map->cache_type == REGCACHE_NONE) {
+ if (map->bus->read &&
+ (regmap_volatile_range(map, reg, val_count) || map->cache_bypass ||
+ map->cache_type == REGCACHE_NONE)) {
+ if (map->max_raw_io && map->max_raw_io < val_len) {
+ ret = -E2BIG;
+ goto out;
+ }
+
/* Physical block read if there's no cache involved */
ret = _regmap_raw_read(map, reg, val, val_len);
--
2.4.6
This allows to read/write up to 32 bytes of data and is to be prefered
if supported before the register read/write smbus support.
Signed-off-by: Markus Pargmann <[email protected]>
---
drivers/base/regmap/regmap-i2c.c | 46 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 46 insertions(+)
diff --git a/drivers/base/regmap/regmap-i2c.c b/drivers/base/regmap/regmap-i2c.c
index 4b76e33110a2..2de6eb4e6ec3 100644
--- a/drivers/base/regmap/regmap-i2c.c
+++ b/drivers/base/regmap/regmap-i2c.c
@@ -209,11 +209,57 @@ static struct regmap_bus regmap_i2c = {
.val_format_endian_default = REGMAP_ENDIAN_BIG,
};
+static int regmap_i2c_smbus_i2c_write(void *context, const void *data,
+ size_t count)
+{
+ struct device *dev = context;
+ struct i2c_client *i2c = to_i2c_client(dev);
+
+ if (count < 1 || count >= I2C_SMBUS_BLOCK_MAX)
+ return -EINVAL;
+
+ --count;
+ return i2c_smbus_write_i2c_block_data(i2c, ((u8 *)data)[0], count,
+ ((u8 *)data + 1));
+}
+
+static int regmap_i2c_smbus_i2c_read(void *context, const void *reg,
+ size_t reg_size, void *val,
+ size_t val_size)
+{
+ struct device *dev = context;
+ struct i2c_client *i2c = to_i2c_client(dev);
+ int ret;
+
+ if (reg_size != 1)
+ return -EINVAL;
+ if (val_size < 1 || val_size >= I2C_SMBUS_BLOCK_MAX)
+ return -EINVAL;
+
+ ret = i2c_smbus_read_i2c_block_data(i2c, ((u8 *)reg)[0], val_size, val);
+ if (ret == val_size)
+ return 0;
+ else if (ret < 0)
+ return ret;
+ else
+ return -EIO;
+}
+
+static struct regmap_bus regmap_i2c_smbus_i2c_block = {
+ .write = regmap_i2c_smbus_i2c_write,
+ .read = regmap_i2c_smbus_i2c_read,
+ .max_raw_io = I2C_SMBUS_BLOCK_MAX,
+};
+
static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c,
const struct regmap_config *config)
{
if (i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C))
return ®map_i2c;
+ else if (config->reg_bits == 8 &&
+ i2c_check_functionality(i2c->adapter,
+ I2C_FUNC_SMBUS_I2C_BLOCK))
+ return ®map_i2c_smbus_i2c_block;
else if (config->val_bits == 16 && config->reg_bits == 8 &&
i2c_check_functionality(i2c->adapter,
I2C_FUNC_SMBUS_WORD_DATA))
--
2.4.6
Valid irqs are > 0. This patch fixes the check which fails for the new
spi driver part if no interrupt was given.
Signed-off-by: Markus Pargmann <[email protected]>
---
drivers/iio/accel/bmc150-accel.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel.c
index 4e70f51c2370..fe2d2316158f 100644
--- a/drivers/iio/accel/bmc150-accel.c
+++ b/drivers/iio/accel/bmc150-accel.c
@@ -1660,10 +1660,10 @@ static int bmc150_accel_probe(struct i2c_client *client,
return ret;
}
- if (client->irq < 0)
+ if (client->irq <= 0)
client->irq = bmc150_accel_gpio_probe(client, data);
- if (client->irq >= 0) {
+ if (client->irq > 0) {
ret = devm_request_threaded_irq(
&client->dev, client->irq,
bmc150_accel_irq_handler,
--
2.4.6
This replaces all usage of direct i2c accesses with regmap accesses.
Signed-off-by: Markus Pargmann <[email protected]>
---
drivers/iio/accel/Kconfig | 2 +
drivers/iio/accel/bmc150-accel.c | 225 +++++++++++++++++----------------------
2 files changed, 101 insertions(+), 126 deletions(-)
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
index 00e7bcbdbe24..01dd03d194d1 100644
--- a/drivers/iio/accel/Kconfig
+++ b/drivers/iio/accel/Kconfig
@@ -22,6 +22,8 @@ config BMC150_ACCEL
depends on I2C
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
+ select REGMAP
+ select REGMAP_I2C
help
Say yes here to build support for the following Bosch accelerometers:
BMC150, BMI055, BMA250E, BMA222E, BMA255, BMA280.
diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel.c
index fe2d2316158f..1484e956482e 100644
--- a/drivers/iio/accel/bmc150-accel.c
+++ b/drivers/iio/accel/bmc150-accel.c
@@ -35,6 +35,7 @@
#include <linux/iio/trigger.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
+#include <linux/regmap.h>
#define BMC150_ACCEL_DRV_NAME "bmc150_accel"
#define BMC150_ACCEL_IRQ_NAME "bmc150_accel_event"
@@ -185,6 +186,8 @@ enum bmc150_accel_trigger_id {
struct bmc150_accel_data {
struct i2c_client *client;
+ struct regmap *regmap;
+ struct device *dev;
struct bmc150_accel_interrupt interrupts[BMC150_ACCEL_INTERRUPTS];
atomic_t active_intr;
struct bmc150_accel_trigger triggers[BMC150_ACCEL_TRIGGERS];
@@ -241,6 +244,14 @@ static const struct {
{500000, BMC150_ACCEL_SLEEP_500_MS},
{1000000, BMC150_ACCEL_SLEEP_1_SEC} };
+static const struct regmap_config bmc150_i2c_regmap_conf = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 0x3f,
+
+ .use_single_rw = false,
+ .cache_type = REGCACHE_NONE,
+};
static int bmc150_accel_set_mode(struct bmc150_accel_data *data,
enum bmc150_power_modes mode,
@@ -270,8 +281,7 @@ static int bmc150_accel_set_mode(struct bmc150_accel_data *data,
dev_dbg(&data->client->dev, "Set Mode bits %x\n", lpw_bits);
- ret = i2c_smbus_write_byte_data(data->client,
- BMC150_ACCEL_REG_PMU_LPW, lpw_bits);
+ ret = regmap_write(data->regmap, BMC150_ACCEL_REG_PMU_LPW, lpw_bits);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_pmu_lpw\n");
return ret;
@@ -289,8 +299,7 @@ static int bmc150_accel_set_bw(struct bmc150_accel_data *data, int val,
for (i = 0; i < ARRAY_SIZE(bmc150_accel_samp_freq_table); ++i) {
if (bmc150_accel_samp_freq_table[i].val == val &&
bmc150_accel_samp_freq_table[i].val2 == val2) {
- ret = i2c_smbus_write_byte_data(
- data->client,
+ ret = regmap_write(data->regmap,
BMC150_ACCEL_REG_PMU_BW,
bmc150_accel_samp_freq_table[i].bw_bits);
if (ret < 0)
@@ -307,26 +316,19 @@ static int bmc150_accel_set_bw(struct bmc150_accel_data *data, int val,
static int bmc150_accel_update_slope(struct bmc150_accel_data *data)
{
- int ret, val;
+ int ret;
- ret = i2c_smbus_write_byte_data(data->client, BMC150_ACCEL_REG_INT_6,
+ ret = regmap_write(data->regmap, BMC150_ACCEL_REG_INT_6,
data->slope_thres);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_int_6\n");
return ret;
}
- ret = i2c_smbus_read_byte_data(data->client, BMC150_ACCEL_REG_INT_5);
+ ret = regmap_update_bits(data->regmap, BMC150_ACCEL_REG_INT_5,
+ BMC150_ACCEL_SLOPE_DUR_MASK, data->slope_dur);
if (ret < 0) {
- dev_err(&data->client->dev, "Error reading reg_int_5\n");
- return ret;
- }
-
- val = (ret & ~BMC150_ACCEL_SLOPE_DUR_MASK) | data->slope_dur;
- ret = i2c_smbus_write_byte_data(data->client, BMC150_ACCEL_REG_INT_5,
- val);
- if (ret < 0) {
- dev_err(&data->client->dev, "Error write reg_int_5\n");
+ dev_err(&data->client->dev, "Error updating reg_int_5\n");
return ret;
}
@@ -348,17 +350,18 @@ static int bmc150_accel_any_motion_setup(struct bmc150_accel_trigger *t,
static int bmc150_accel_chip_init(struct bmc150_accel_data *data)
{
int ret;
+ unsigned int val;
- ret = i2c_smbus_read_byte_data(data->client, BMC150_ACCEL_REG_CHIP_ID);
+ ret = regmap_read(data->regmap, BMC150_ACCEL_REG_CHIP_ID, &val);
if (ret < 0) {
dev_err(&data->client->dev,
"Error: Reading chip id\n");
return ret;
}
- dev_dbg(&data->client->dev, "Chip Id %x\n", ret);
- if (ret != data->chip_info->chip_id) {
- dev_err(&data->client->dev, "Invalid chip %x\n", ret);
+ dev_dbg(&data->client->dev, "Chip Id %x\n", val);
+ if (val != data->chip_info->chip_id) {
+ dev_err(&data->client->dev, "Invalid chip %x\n", val);
return -ENODEV;
}
@@ -372,9 +375,8 @@ static int bmc150_accel_chip_init(struct bmc150_accel_data *data)
return ret;
/* Set Default Range */
- ret = i2c_smbus_write_byte_data(data->client,
- BMC150_ACCEL_REG_PMU_RANGE,
- BMC150_ACCEL_DEF_RANGE_4G);
+ ret = regmap_write(data->regmap, BMC150_ACCEL_REG_PMU_RANGE,
+ BMC150_ACCEL_DEF_RANGE_4G);
if (ret < 0) {
dev_err(&data->client->dev,
"Error writing reg_pmu_range\n");
@@ -391,10 +393,9 @@ static int bmc150_accel_chip_init(struct bmc150_accel_data *data)
return ret;
/* Set default as latched interrupts */
- ret = i2c_smbus_write_byte_data(data->client,
- BMC150_ACCEL_REG_INT_RST_LATCH,
- BMC150_ACCEL_INT_MODE_LATCH_INT |
- BMC150_ACCEL_INT_MODE_LATCH_RESET);
+ ret = regmap_write(data->regmap, BMC150_ACCEL_REG_INT_RST_LATCH,
+ BMC150_ACCEL_INT_MODE_LATCH_INT |
+ BMC150_ACCEL_INT_MODE_LATCH_RESET);
if (ret < 0) {
dev_err(&data->client->dev,
"Error writing reg_int_rst_latch\n");
@@ -527,38 +528,18 @@ static int bmc150_accel_set_interrupt(struct bmc150_accel_data *data, int i,
return ret;
/* map the interrupt to the appropriate pins */
- ret = i2c_smbus_read_byte_data(data->client, info->map_reg);
- if (ret < 0) {
- dev_err(&data->client->dev, "Error reading reg_int_map\n");
- goto out_fix_power_state;
- }
- if (state)
- ret |= info->map_bitmask;
- else
- ret &= ~info->map_bitmask;
-
- ret = i2c_smbus_write_byte_data(data->client, info->map_reg,
- ret);
+ ret = regmap_update_bits(data->regmap, info->map_reg, info->map_bitmask,
+ (state ? info->map_bitmask : 0));
if (ret < 0) {
- dev_err(&data->client->dev, "Error writing reg_int_map\n");
+ dev_err(&data->client->dev, "Error updating reg_int_map\n");
goto out_fix_power_state;
}
/* enable/disable the interrupt */
- ret = i2c_smbus_read_byte_data(data->client, info->en_reg);
- if (ret < 0) {
- dev_err(&data->client->dev, "Error reading reg_int_en\n");
- goto out_fix_power_state;
- }
-
- if (state)
- ret |= info->en_bitmask;
- else
- ret &= ~info->en_bitmask;
-
- ret = i2c_smbus_write_byte_data(data->client, info->en_reg, ret);
+ ret = regmap_update_bits(data->regmap, info->en_reg, info->en_bitmask,
+ (state ? info->en_bitmask : 0));
if (ret < 0) {
- dev_err(&data->client->dev, "Error writing reg_int_en\n");
+ dev_err(&data->client->dev, "Error updating reg_int_en\n");
goto out_fix_power_state;
}
@@ -581,8 +562,7 @@ static int bmc150_accel_set_scale(struct bmc150_accel_data *data, int val)
for (i = 0; i < ARRAY_SIZE(data->chip_info->scale_table); ++i) {
if (data->chip_info->scale_table[i].scale == val) {
- ret = i2c_smbus_write_byte_data(
- data->client,
+ ret = regmap_write(data->regmap,
BMC150_ACCEL_REG_PMU_RANGE,
data->chip_info->scale_table[i].reg_range);
if (ret < 0) {
@@ -602,16 +582,17 @@ static int bmc150_accel_set_scale(struct bmc150_accel_data *data, int val)
static int bmc150_accel_get_temp(struct bmc150_accel_data *data, int *val)
{
int ret;
+ unsigned int value;
mutex_lock(&data->mutex);
- ret = i2c_smbus_read_byte_data(data->client, BMC150_ACCEL_REG_TEMP);
+ ret = regmap_read(data->regmap, BMC150_ACCEL_REG_TEMP, &value);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_temp\n");
mutex_unlock(&data->mutex);
return ret;
}
- *val = sign_extend32(ret, 7);
+ *val = sign_extend32(value, 7);
mutex_unlock(&data->mutex);
@@ -624,6 +605,7 @@ static int bmc150_accel_get_axis(struct bmc150_accel_data *data,
{
int ret;
int axis = chan->scan_index;
+ unsigned int raw_val;
mutex_lock(&data->mutex);
ret = bmc150_accel_set_power_state(data, true);
@@ -632,15 +614,15 @@ static int bmc150_accel_get_axis(struct bmc150_accel_data *data,
return ret;
}
- ret = i2c_smbus_read_word_data(data->client,
- BMC150_ACCEL_AXIS_TO_REG(axis));
+ ret = regmap_bulk_read(data->regmap, BMC150_ACCEL_AXIS_TO_REG(axis),
+ &raw_val, 2);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading axis %d\n", axis);
bmc150_accel_set_power_state(data, false);
mutex_unlock(&data->mutex);
return ret;
}
- *val = sign_extend32(ret >> chan->scan_type.shift,
+ *val = sign_extend32(raw_val >> chan->scan_type.shift,
chan->scan_type.realbits - 1);
ret = bmc150_accel_set_power_state(data, false);
mutex_unlock(&data->mutex);
@@ -904,52 +886,37 @@ static int bmc150_accel_set_watermark(struct iio_dev *indio_dev, unsigned val)
* We must read at least one full frame in one burst, otherwise the rest of the
* frame data is discarded.
*/
-static int bmc150_accel_fifo_transfer(const struct i2c_client *client,
+static int bmc150_accel_fifo_transfer(struct bmc150_accel_data *data,
char *buffer, int samples)
{
int sample_length = 3 * 2;
- u8 reg_fifo_data = BMC150_ACCEL_REG_FIFO_DATA;
- int ret = -EIO;
-
- if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
- struct i2c_msg msg[2] = {
- {
- .addr = client->addr,
- .flags = 0,
- .buf = ®_fifo_data,
- .len = sizeof(reg_fifo_data),
- },
- {
- .addr = client->addr,
- .flags = I2C_M_RD,
- .buf = (u8 *)buffer,
- .len = samples * sample_length,
- }
- };
+ int ret;
+ int total_length = samples * sample_length;
+ int i, step;
- ret = i2c_transfer(client->adapter, msg, 2);
- if (ret != 2)
- ret = -EIO;
- else
- ret = 0;
- } else {
- int i, step = I2C_SMBUS_BLOCK_MAX / sample_length;
-
- for (i = 0; i < samples * sample_length; i += step) {
- ret = i2c_smbus_read_i2c_block_data(client,
- reg_fifo_data, step,
- &buffer[i]);
- if (ret != step) {
- ret = -EIO;
- break;
- }
+ ret = regmap_raw_read(data->regmap, BMC150_ACCEL_REG_FIFO_DATA, buffer,
+ total_length);
+ if (ret != -E2BIG) {
+ if (ret)
+ dev_err(data->dev, "Error transferring data from fifo\n");
+ return ret;
+ }
- ret = 0;
- }
+ /*
+ * Seems we have a bus with size limitation so we have to execute
+ * multiple reads
+ */
+ step = regmap_get_raw_io_max(data->regmap) / sample_length;
+ for (i = -1; i < samples * sample_length; i += step) {
+ ret = regmap_raw_read(data->regmap, BMC150_ACCEL_REG_FIFO_DATA,
+ &buffer[i], step);
+ if (ret)
+ break;
}
if (ret)
- dev_err(&client->dev, "Error transferring data from fifo\n");
+ dev_err(data->dev, "Error transferring data from fifo in single steps of %zu\n",
+ step);
return ret;
}
@@ -963,14 +930,15 @@ static int __bmc150_accel_fifo_flush(struct iio_dev *indio_dev,
u16 buffer[BMC150_ACCEL_FIFO_LENGTH * 3];
int64_t tstamp;
uint64_t sample_period;
- ret = i2c_smbus_read_byte_data(data->client,
- BMC150_ACCEL_REG_FIFO_STATUS);
+ unsigned int val;
+
+ ret = regmap_read(data->regmap, BMC150_ACCEL_REG_FIFO_STATUS, &val);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_fifo_status\n");
return ret;
}
- count = ret & 0x7F;
+ count = val & 0x7F;
if (!count)
return 0;
@@ -1009,7 +977,7 @@ static int __bmc150_accel_fifo_flush(struct iio_dev *indio_dev,
if (samples && count > samples)
count = samples;
- ret = bmc150_accel_fifo_transfer(data->client, (u8 *)buffer, count);
+ ret = bmc150_accel_fifo_transfer(data, (u8 *)buffer, count);
if (ret)
return ret;
@@ -1206,17 +1174,19 @@ static irqreturn_t bmc150_accel_trigger_handler(int irq, void *p)
struct iio_dev *indio_dev = pf->indio_dev;
struct bmc150_accel_data *data = iio_priv(indio_dev);
int bit, ret, i = 0;
+ unsigned int raw_val;
mutex_lock(&data->mutex);
for_each_set_bit(bit, indio_dev->active_scan_mask,
indio_dev->masklength) {
- ret = i2c_smbus_read_word_data(data->client,
- BMC150_ACCEL_AXIS_TO_REG(bit));
+ ret = regmap_bulk_read(data->regmap,
+ BMC150_ACCEL_AXIS_TO_REG(bit), &raw_val,
+ 2);
if (ret < 0) {
mutex_unlock(&data->mutex);
goto err_read;
}
- data->buffer[i++] = ret;
+ data->buffer[i++] = raw_val;
}
mutex_unlock(&data->mutex);
@@ -1240,10 +1210,9 @@ static int bmc150_accel_trig_try_reen(struct iio_trigger *trig)
mutex_lock(&data->mutex);
/* clear any latched interrupt */
- ret = i2c_smbus_write_byte_data(data->client,
- BMC150_ACCEL_REG_INT_RST_LATCH,
- BMC150_ACCEL_INT_MODE_LATCH_INT |
- BMC150_ACCEL_INT_MODE_LATCH_RESET);
+ ret = regmap_write(data->regmap, BMC150_ACCEL_REG_INT_RST_LATCH,
+ BMC150_ACCEL_INT_MODE_LATCH_INT |
+ BMC150_ACCEL_INT_MODE_LATCH_RESET);
mutex_unlock(&data->mutex);
if (ret < 0) {
dev_err(&data->client->dev,
@@ -1300,34 +1269,34 @@ static int bmc150_accel_handle_roc_event(struct iio_dev *indio_dev)
struct bmc150_accel_data *data = iio_priv(indio_dev);
int dir;
int ret;
+ unsigned int val;
- ret = i2c_smbus_read_byte_data(data->client,
- BMC150_ACCEL_REG_INT_STATUS_2);
+ ret = regmap_read(data->regmap, BMC150_ACCEL_REG_INT_STATUS_2, &val);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_int_status_2\n");
return ret;
}
- if (ret & BMC150_ACCEL_ANY_MOTION_BIT_SIGN)
+ if (val & BMC150_ACCEL_ANY_MOTION_BIT_SIGN)
dir = IIO_EV_DIR_FALLING;
else
dir = IIO_EV_DIR_RISING;
- if (ret & BMC150_ACCEL_ANY_MOTION_BIT_X)
+ if (val & BMC150_ACCEL_ANY_MOTION_BIT_X)
iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL,
0,
IIO_MOD_X,
IIO_EV_TYPE_ROC,
dir),
data->timestamp);
- if (ret & BMC150_ACCEL_ANY_MOTION_BIT_Y)
+ if (val & BMC150_ACCEL_ANY_MOTION_BIT_Y)
iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL,
0,
IIO_MOD_Y,
IIO_EV_TYPE_ROC,
dir),
data->timestamp);
- if (ret & BMC150_ACCEL_ANY_MOTION_BIT_Z)
+ if (val & BMC150_ACCEL_ANY_MOTION_BIT_Z)
iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL,
0,
IIO_MOD_Z,
@@ -1360,10 +1329,9 @@ static irqreturn_t bmc150_accel_irq_thread_handler(int irq, void *private)
}
if (ack) {
- ret = i2c_smbus_write_byte_data(data->client,
- BMC150_ACCEL_REG_INT_RST_LATCH,
- BMC150_ACCEL_INT_MODE_LATCH_INT |
- BMC150_ACCEL_INT_MODE_LATCH_RESET);
+ ret = regmap_write(data->regmap, BMC150_ACCEL_REG_INT_RST_LATCH,
+ BMC150_ACCEL_INT_MODE_LATCH_INT |
+ BMC150_ACCEL_INT_MODE_LATCH_RESET);
if (ret)
dev_err(&data->client->dev, "Error writing reg_int_rst_latch\n");
ret = IRQ_HANDLED;
@@ -1516,7 +1484,7 @@ static int bmc150_accel_fifo_set_mode(struct bmc150_accel_data *data)
u8 reg = BMC150_ACCEL_REG_FIFO_CONFIG1;
int ret;
- ret = i2c_smbus_write_byte_data(data->client, reg, data->fifo_mode);
+ ret = regmap_write(data->regmap, reg, data->fifo_mode);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_fifo_config1\n");
return ret;
@@ -1525,9 +1493,8 @@ static int bmc150_accel_fifo_set_mode(struct bmc150_accel_data *data)
if (!data->fifo_mode)
return 0;
- ret = i2c_smbus_write_byte_data(data->client,
- BMC150_ACCEL_REG_FIFO_CONFIG0,
- data->watermark);
+ ret = regmap_write(data->regmap, BMC150_ACCEL_REG_FIFO_CONFIG0,
+ data->watermark);
if (ret < 0)
dev_err(&data->client->dev, "Error writing reg_fifo_config0\n");
@@ -1627,6 +1594,13 @@ static int bmc150_accel_probe(struct i2c_client *client,
data = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
data->client = client;
+ data->dev = &client->dev;
+
+ data->regmap = devm_regmap_init_i2c(client, &bmc150_i2c_regmap_conf);
+ if (IS_ERR(data->regmap)) {
+ dev_err(&client->dev, "Failed to initialize i2c regmap\n");
+ return PTR_ERR(data->regmap);
+ }
if (id) {
name = id->name;
@@ -1680,9 +1654,8 @@ static int bmc150_accel_probe(struct i2c_client *client,
* want to use latch mode when we can to prevent interrupt
* flooding.
*/
- ret = i2c_smbus_write_byte_data(data->client,
- BMC150_ACCEL_REG_INT_RST_LATCH,
- BMC150_ACCEL_INT_MODE_LATCH_RESET);
+ ret = regmap_write(data->regmap, BMC150_ACCEL_REG_INT_RST_LATCH,
+ BMC150_ACCEL_INT_MODE_LATCH_RESET);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_int_rst_latch\n");
goto err_buffer_cleanup;
--
2.4.6
i2c_client struct is now only used for debugging output. We can use the
device struct as well so we can remove all struct i2c_client usage.
Signed-off-by: Markus Pargmann <[email protected]>
---
drivers/iio/accel/bmc150-accel.c | 120 +++++++++++++++++++--------------------
1 file changed, 58 insertions(+), 62 deletions(-)
diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel.c
index 1484e956482e..d75e1b0aa7e9 100644
--- a/drivers/iio/accel/bmc150-accel.c
+++ b/drivers/iio/accel/bmc150-accel.c
@@ -185,9 +185,9 @@ enum bmc150_accel_trigger_id {
};
struct bmc150_accel_data {
- struct i2c_client *client;
struct regmap *regmap;
struct device *dev;
+ int irq;
struct bmc150_accel_interrupt interrupts[BMC150_ACCEL_INTERRUPTS];
atomic_t active_intr;
struct bmc150_accel_trigger triggers[BMC150_ACCEL_TRIGGERS];
@@ -279,11 +279,11 @@ static int bmc150_accel_set_mode(struct bmc150_accel_data *data,
lpw_bits = mode << BMC150_ACCEL_PMU_MODE_SHIFT;
lpw_bits |= (dur_val << BMC150_ACCEL_PMU_BIT_SLEEP_DUR_SHIFT);
- dev_dbg(&data->client->dev, "Set Mode bits %x\n", lpw_bits);
+ dev_dbg(data->dev, "Set Mode bits %x\n", lpw_bits);
ret = regmap_write(data->regmap, BMC150_ACCEL_REG_PMU_LPW, lpw_bits);
if (ret < 0) {
- dev_err(&data->client->dev, "Error writing reg_pmu_lpw\n");
+ dev_err(data->dev, "Error writing reg_pmu_lpw\n");
return ret;
}
@@ -321,18 +321,18 @@ static int bmc150_accel_update_slope(struct bmc150_accel_data *data)
ret = regmap_write(data->regmap, BMC150_ACCEL_REG_INT_6,
data->slope_thres);
if (ret < 0) {
- dev_err(&data->client->dev, "Error writing reg_int_6\n");
+ dev_err(data->dev, "Error writing reg_int_6\n");
return ret;
}
ret = regmap_update_bits(data->regmap, BMC150_ACCEL_REG_INT_5,
BMC150_ACCEL_SLOPE_DUR_MASK, data->slope_dur);
if (ret < 0) {
- dev_err(&data->client->dev, "Error updating reg_int_5\n");
+ dev_err(data->dev, "Error updating reg_int_5\n");
return ret;
}
- dev_dbg(&data->client->dev, "%s: %x %x\n", __func__, data->slope_thres,
+ dev_dbg(data->dev, "%s: %x %x\n", __func__, data->slope_thres,
data->slope_dur);
return ret;
@@ -354,14 +354,14 @@ static int bmc150_accel_chip_init(struct bmc150_accel_data *data)
ret = regmap_read(data->regmap, BMC150_ACCEL_REG_CHIP_ID, &val);
if (ret < 0) {
- dev_err(&data->client->dev,
+ dev_err(data->dev,
"Error: Reading chip id\n");
return ret;
}
- dev_dbg(&data->client->dev, "Chip Id %x\n", val);
+ dev_dbg(data->dev, "Chip Id %x\n", val);
if (val != data->chip_info->chip_id) {
- dev_err(&data->client->dev, "Invalid chip %x\n", val);
+ dev_err(data->dev, "Invalid chip %x\n", val);
return -ENODEV;
}
@@ -378,8 +378,7 @@ static int bmc150_accel_chip_init(struct bmc150_accel_data *data)
ret = regmap_write(data->regmap, BMC150_ACCEL_REG_PMU_RANGE,
BMC150_ACCEL_DEF_RANGE_4G);
if (ret < 0) {
- dev_err(&data->client->dev,
- "Error writing reg_pmu_range\n");
+ dev_err(data->dev, "Error writing reg_pmu_range\n");
return ret;
}
@@ -397,7 +396,7 @@ static int bmc150_accel_chip_init(struct bmc150_accel_data *data)
BMC150_ACCEL_INT_MODE_LATCH_INT |
BMC150_ACCEL_INT_MODE_LATCH_RESET);
if (ret < 0) {
- dev_err(&data->client->dev,
+ dev_err(data->dev,
"Error writing reg_int_rst_latch\n");
return ret;
}
@@ -439,16 +438,16 @@ static int bmc150_accel_set_power_state(struct bmc150_accel_data *data, bool on)
int ret;
if (on)
- ret = pm_runtime_get_sync(&data->client->dev);
+ ret = pm_runtime_get_sync(data->dev);
else {
- pm_runtime_mark_last_busy(&data->client->dev);
- ret = pm_runtime_put_autosuspend(&data->client->dev);
+ pm_runtime_mark_last_busy(data->dev);
+ ret = pm_runtime_put_autosuspend(data->dev);
}
if (ret < 0) {
- dev_err(&data->client->dev,
+ dev_err(data->dev,
"Failed: bmc150_accel_set_power_state for %d\n", on);
if (on)
- pm_runtime_put_noidle(&data->client->dev);
+ pm_runtime_put_noidle(data->dev);
return ret;
}
@@ -531,7 +530,7 @@ static int bmc150_accel_set_interrupt(struct bmc150_accel_data *data, int i,
ret = regmap_update_bits(data->regmap, info->map_reg, info->map_bitmask,
(state ? info->map_bitmask : 0));
if (ret < 0) {
- dev_err(&data->client->dev, "Error updating reg_int_map\n");
+ dev_err(data->dev, "Error updating reg_int_map\n");
goto out_fix_power_state;
}
@@ -539,7 +538,7 @@ static int bmc150_accel_set_interrupt(struct bmc150_accel_data *data, int i,
ret = regmap_update_bits(data->regmap, info->en_reg, info->en_bitmask,
(state ? info->en_bitmask : 0));
if (ret < 0) {
- dev_err(&data->client->dev, "Error updating reg_int_en\n");
+ dev_err(data->dev, "Error updating reg_int_en\n");
goto out_fix_power_state;
}
@@ -566,7 +565,7 @@ static int bmc150_accel_set_scale(struct bmc150_accel_data *data, int val)
BMC150_ACCEL_REG_PMU_RANGE,
data->chip_info->scale_table[i].reg_range);
if (ret < 0) {
- dev_err(&data->client->dev,
+ dev_err(data->dev,
"Error writing pmu_range\n");
return ret;
}
@@ -588,7 +587,7 @@ static int bmc150_accel_get_temp(struct bmc150_accel_data *data, int *val)
ret = regmap_read(data->regmap, BMC150_ACCEL_REG_TEMP, &value);
if (ret < 0) {
- dev_err(&data->client->dev, "Error reading reg_temp\n");
+ dev_err(data->dev, "Error reading reg_temp\n");
mutex_unlock(&data->mutex);
return ret;
}
@@ -617,7 +616,7 @@ static int bmc150_accel_get_axis(struct bmc150_accel_data *data,
ret = regmap_bulk_read(data->regmap, BMC150_ACCEL_AXIS_TO_REG(axis),
&raw_val, 2);
if (ret < 0) {
- dev_err(&data->client->dev, "Error reading axis %d\n", axis);
+ dev_err(data->dev, "Error reading axis %d\n", axis);
bmc150_accel_set_power_state(data, false);
mutex_unlock(&data->mutex);
return ret;
@@ -934,7 +933,7 @@ static int __bmc150_accel_fifo_flush(struct iio_dev *indio_dev,
ret = regmap_read(data->regmap, BMC150_ACCEL_REG_FIFO_STATUS, &val);
if (ret < 0) {
- dev_err(&data->client->dev, "Error reading reg_fifo_status\n");
+ dev_err(data->dev, "Error reading reg_fifo_status\n");
return ret;
}
@@ -1215,7 +1214,7 @@ static int bmc150_accel_trig_try_reen(struct iio_trigger *trig)
BMC150_ACCEL_INT_MODE_LATCH_RESET);
mutex_unlock(&data->mutex);
if (ret < 0) {
- dev_err(&data->client->dev,
+ dev_err(data->dev,
"Error writing reg_int_rst_latch\n");
return ret;
}
@@ -1273,7 +1272,7 @@ static int bmc150_accel_handle_roc_event(struct iio_dev *indio_dev)
ret = regmap_read(data->regmap, BMC150_ACCEL_REG_INT_STATUS_2, &val);
if (ret < 0) {
- dev_err(&data->client->dev, "Error reading reg_int_status_2\n");
+ dev_err(data->dev, "Error reading reg_int_status_2\n");
return ret;
}
@@ -1333,7 +1332,7 @@ static irqreturn_t bmc150_accel_irq_thread_handler(int irq, void *private)
BMC150_ACCEL_INT_MODE_LATCH_INT |
BMC150_ACCEL_INT_MODE_LATCH_RESET);
if (ret)
- dev_err(&data->client->dev, "Error writing reg_int_rst_latch\n");
+ dev_err(data->dev, "Error writing reg_int_rst_latch\n");
ret = IRQ_HANDLED;
} else {
ret = IRQ_NONE;
@@ -1385,17 +1384,13 @@ static const char *bmc150_accel_match_acpi_device(struct device *dev, int *data)
return dev_name(dev);
}
-static int bmc150_accel_gpio_probe(struct i2c_client *client,
- struct bmc150_accel_data *data)
+static int bmc150_accel_gpio_probe(struct bmc150_accel_data *data)
{
struct device *dev;
struct gpio_desc *gpio;
int ret;
- if (!client)
- return -EINVAL;
-
- dev = &client->dev;
+ dev = data->dev;
/* data ready gpio interrupt pin */
gpio = devm_gpiod_get_index(dev, BMC150_ACCEL_GPIO_NAME, 0, GPIOD_IN);
@@ -1448,7 +1443,7 @@ static int bmc150_accel_triggers_setup(struct iio_dev *indio_dev,
for (i = 0; i < BMC150_ACCEL_TRIGGERS; i++) {
struct bmc150_accel_trigger *t = &data->triggers[i];
- t->indio_trig = devm_iio_trigger_alloc(&data->client->dev,
+ t->indio_trig = devm_iio_trigger_alloc(data->dev,
bmc150_accel_triggers[i].name,
indio_dev->name,
indio_dev->id);
@@ -1457,7 +1452,7 @@ static int bmc150_accel_triggers_setup(struct iio_dev *indio_dev,
break;
}
- t->indio_trig->dev.parent = &data->client->dev;
+ t->indio_trig->dev.parent = data->dev;
t->indio_trig->ops = &bmc150_accel_trigger_ops;
t->intr = bmc150_accel_triggers[i].intr;
t->data = data;
@@ -1486,7 +1481,7 @@ static int bmc150_accel_fifo_set_mode(struct bmc150_accel_data *data)
ret = regmap_write(data->regmap, reg, data->fifo_mode);
if (ret < 0) {
- dev_err(&data->client->dev, "Error writing reg_fifo_config1\n");
+ dev_err(data->dev, "Error writing reg_fifo_config1\n");
return ret;
}
@@ -1496,7 +1491,7 @@ static int bmc150_accel_fifo_set_mode(struct bmc150_accel_data *data)
ret = regmap_write(data->regmap, BMC150_ACCEL_REG_FIFO_CONFIG0,
data->watermark);
if (ret < 0)
- dev_err(&data->client->dev, "Error writing reg_fifo_config0\n");
+ dev_err(data->dev, "Error writing reg_fifo_config0\n");
return ret;
}
@@ -1586,6 +1581,7 @@ static int bmc150_accel_probe(struct i2c_client *client,
int ret;
const char *name = NULL;
int chip_id = 0;
+ struct device *dev;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev)
@@ -1593,12 +1589,13 @@ static int bmc150_accel_probe(struct i2c_client *client,
data = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
- data->client = client;
data->dev = &client->dev;
+ dev = &client->dev;
+ data->irq = client->irq;
data->regmap = devm_regmap_init_i2c(client, &bmc150_i2c_regmap_conf);
if (IS_ERR(data->regmap)) {
- dev_err(&client->dev, "Failed to initialize i2c regmap\n");
+ dev_err(dev, "Failed to initialize i2c regmap\n");
return PTR_ERR(data->regmap);
}
@@ -1607,8 +1604,8 @@ static int bmc150_accel_probe(struct i2c_client *client,
chip_id = id->driver_data;
}
- if (ACPI_HANDLE(&client->dev))
- name = bmc150_accel_match_acpi_device(&client->dev, &chip_id);
+ if (ACPI_HANDLE(dev))
+ name = bmc150_accel_match_acpi_device(dev, &chip_id);
data->chip_info = &bmc150_accel_chip_info_tbl[chip_id];
@@ -1618,7 +1615,7 @@ static int bmc150_accel_probe(struct i2c_client *client,
mutex_init(&data->mutex);
- indio_dev->dev.parent = &client->dev;
+ indio_dev->dev.parent = dev;
indio_dev->channels = data->chip_info->channels;
indio_dev->num_channels = data->chip_info->num_channels;
indio_dev->name = name;
@@ -1630,16 +1627,16 @@ static int bmc150_accel_probe(struct i2c_client *client,
bmc150_accel_trigger_handler,
&bmc150_accel_buffer_ops);
if (ret < 0) {
- dev_err(&client->dev, "Failed: iio triggered buffer setup\n");
+ dev_err(data->dev, "Failed: iio triggered buffer setup\n");
return ret;
}
- if (client->irq <= 0)
- client->irq = bmc150_accel_gpio_probe(client, data);
+ if (data->irq <= 0)
+ data->irq = bmc150_accel_gpio_probe(data);
- if (client->irq > 0) {
+ if (data->irq > 0) {
ret = devm_request_threaded_irq(
- &client->dev, client->irq,
+ data->dev, data->irq,
bmc150_accel_irq_handler,
bmc150_accel_irq_thread_handler,
IRQF_TRIGGER_RISING,
@@ -1657,7 +1654,7 @@ static int bmc150_accel_probe(struct i2c_client *client,
ret = regmap_write(data->regmap, BMC150_ACCEL_REG_INT_RST_LATCH,
BMC150_ACCEL_INT_MODE_LATCH_RESET);
if (ret < 0) {
- dev_err(&data->client->dev, "Error writing reg_int_rst_latch\n");
+ dev_err(data->dev, "Error writing reg_int_rst_latch\n");
goto err_buffer_cleanup;
}
@@ -1678,18 +1675,17 @@ static int bmc150_accel_probe(struct i2c_client *client,
ret = iio_device_register(indio_dev);
if (ret < 0) {
- dev_err(&client->dev, "Unable to register iio device\n");
+ dev_err(data->dev, "Unable to register iio device\n");
goto err_trigger_unregister;
}
- ret = pm_runtime_set_active(&client->dev);
+ ret = pm_runtime_set_active(dev);
if (ret)
goto err_iio_unregister;
- pm_runtime_enable(&client->dev);
- pm_runtime_set_autosuspend_delay(&client->dev,
- BMC150_AUTO_SUSPEND_DELAY_MS);
- pm_runtime_use_autosuspend(&client->dev);
+ pm_runtime_enable(dev);
+ pm_runtime_set_autosuspend_delay(dev, BMC150_AUTO_SUSPEND_DELAY_MS);
+ pm_runtime_use_autosuspend(dev);
return 0;
@@ -1708,9 +1704,9 @@ static int bmc150_accel_remove(struct i2c_client *client)
struct iio_dev *indio_dev = i2c_get_clientdata(client);
struct bmc150_accel_data *data = iio_priv(indio_dev);
- pm_runtime_disable(&client->dev);
- pm_runtime_set_suspended(&client->dev);
- pm_runtime_put_noidle(&client->dev);
+ pm_runtime_disable(data->dev);
+ pm_runtime_set_suspended(data->dev);
+ pm_runtime_put_noidle(data->dev);
iio_device_unregister(indio_dev);
@@ -1728,7 +1724,7 @@ static int bmc150_accel_remove(struct i2c_client *client)
#ifdef CONFIG_PM_SLEEP
static int bmc150_accel_suspend(struct device *dev)
{
- struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct bmc150_accel_data *data = iio_priv(indio_dev);
mutex_lock(&data->mutex);
@@ -1740,7 +1736,7 @@ static int bmc150_accel_suspend(struct device *dev)
static int bmc150_accel_resume(struct device *dev)
{
- struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct bmc150_accel_data *data = iio_priv(indio_dev);
mutex_lock(&data->mutex);
@@ -1756,11 +1752,11 @@ static int bmc150_accel_resume(struct device *dev)
#ifdef CONFIG_PM
static int bmc150_accel_runtime_suspend(struct device *dev)
{
- struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct bmc150_accel_data *data = iio_priv(indio_dev);
int ret;
- dev_dbg(&data->client->dev, __func__);
+ dev_dbg(data->dev, __func__);
ret = bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_SUSPEND, 0);
if (ret < 0)
return -EAGAIN;
@@ -1770,12 +1766,12 @@ static int bmc150_accel_runtime_suspend(struct device *dev)
static int bmc150_accel_runtime_resume(struct device *dev)
{
- struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct bmc150_accel_data *data = iio_priv(indio_dev);
int ret;
int sleep_val;
- dev_dbg(&data->client->dev, __func__);
+ dev_dbg(data->dev, __func__);
ret = bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_NORMAL, 0);
if (ret < 0)
--
2.4.6
Signed-off-by: Markus Pargmann <[email protected]>
---
drivers/iio/accel/Kconfig | 22 +++--
drivers/iio/accel/Makefile | 3 +-
.../accel/{bmc150-accel.c => bmc150-accel-core.c} | 95 ++++---------------
drivers/iio/accel/bmc150-accel-i2c.c | 101 +++++++++++++++++++++
drivers/iio/accel/bmc150-accel.h | 21 +++++
5 files changed, 156 insertions(+), 86 deletions(-)
rename drivers/iio/accel/{bmc150-accel.c => bmc150-accel-core.c} (95%)
create mode 100644 drivers/iio/accel/bmc150-accel-i2c.c
create mode 100644 drivers/iio/accel/bmc150-accel.h
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
index 01dd03d194d1..c63e981c38ff 100644
--- a/drivers/iio/accel/Kconfig
+++ b/drivers/iio/accel/Kconfig
@@ -18,22 +18,30 @@ config BMA180
module will be called bma180.
config BMC150_ACCEL
- tristate "Bosch BMC150 Accelerometer Driver"
- depends on I2C
- select IIO_BUFFER
- select IIO_TRIGGERED_BUFFER
+ bool "Bosch BMC150 Accelerometer Driver"
select REGMAP
- select REGMAP_I2C
help
Say yes here to build support for the following Bosch accelerometers:
BMC150, BMI055, BMA250E, BMA222E, BMA255, BMA280.
- Currently this only supports the device via an i2c interface.
-
This is a combo module with both accelerometer and magnetometer.
This driver is only implementing accelerometer part, which has
its own address and register map.
+if BMC150_ACCEL
+
+config BMC150_ACCEL_I2C
+ tristate "I2C support"
+ depends on I2C
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+ select REGMAP_I2C
+ help
+ Say yes here to build support for I2C communication with the
+ mentioned accelerometer.
+
+endif
+
config HID_SENSOR_ACCEL_3D
depends on HID_SENSOR_HUB
select IIO_BUFFER
diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile
index ebd2675b2a02..5ef8bdbad092 100644
--- a/drivers/iio/accel/Makefile
+++ b/drivers/iio/accel/Makefile
@@ -4,7 +4,8 @@
# When adding new entries keep the list in alphabetical order
obj-$(CONFIG_BMA180) += bma180.o
-obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel.o
+obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o
+obj-$(CONFIG_BMC150_ACCEL_I2C) += bmc150-accel-i2c.o
obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o
obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o
obj-$(CONFIG_KXSD9) += kxsd9.o
diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel-core.c
similarity index 95%
rename from drivers/iio/accel/bmc150-accel.c
rename to drivers/iio/accel/bmc150-accel-core.c
index d75e1b0aa7e9..8cf2786dd433 100644
--- a/drivers/iio/accel/bmc150-accel.c
+++ b/drivers/iio/accel/bmc150-accel-core.c
@@ -37,6 +37,8 @@
#include <linux/iio/triggered_buffer.h>
#include <linux/regmap.h>
+#include "bmc150-accel.h"
+
#define BMC150_ACCEL_DRV_NAME "bmc150_accel"
#define BMC150_ACCEL_IRQ_NAME "bmc150_accel_event"
#define BMC150_ACCEL_GPIO_NAME "bmc150_accel_int"
@@ -187,7 +189,6 @@ enum bmc150_accel_trigger_id {
struct bmc150_accel_data {
struct regmap *regmap;
struct device *dev;
- int irq;
struct bmc150_accel_interrupt interrupts[BMC150_ACCEL_INTERRUPTS];
atomic_t active_intr;
struct bmc150_accel_trigger triggers[BMC150_ACCEL_TRIGGERS];
@@ -201,6 +202,7 @@ struct bmc150_accel_data {
int ev_enable_state;
int64_t timestamp, old_timestamp; /* Only used in hw fifo mode. */
const struct bmc150_accel_chip_info *chip_info;
+ int irq;
};
static const struct {
@@ -1076,15 +1078,6 @@ static const struct iio_chan_spec bmc150_accel_channels[] =
static const struct iio_chan_spec bma280_accel_channels[] =
BMC150_ACCEL_CHANNELS(14);
-enum {
- bmc150,
- bmi055,
- bma255,
- bma250e,
- bma222e,
- bma280,
-};
-
static const struct bmc150_accel_chip_info bmc150_accel_chip_info_tbl[] = {
[bmc150] = {
.chip_id = 0xFA,
@@ -1573,36 +1566,22 @@ static const struct iio_buffer_setup_ops bmc150_accel_buffer_ops = {
.postdisable = bmc150_accel_buffer_postdisable,
};
-static int bmc150_accel_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq,
+ const char *name, int chip_id, bool block_supported)
{
struct bmc150_accel_data *data;
struct iio_dev *indio_dev;
int ret;
- const char *name = NULL;
- int chip_id = 0;
- struct device *dev;
- indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
if (!indio_dev)
return -ENOMEM;
data = iio_priv(indio_dev);
- i2c_set_clientdata(client, indio_dev);
- data->dev = &client->dev;
- dev = &client->dev;
- data->irq = client->irq;
-
- data->regmap = devm_regmap_init_i2c(client, &bmc150_i2c_regmap_conf);
- if (IS_ERR(data->regmap)) {
- dev_err(dev, "Failed to initialize i2c regmap\n");
- return PTR_ERR(data->regmap);
- }
-
- if (id) {
- name = id->name;
- chip_id = id->driver_data;
- }
+ dev_set_drvdata(dev, indio_dev);
+ data->dev = dev;
+ data->irq = irq;
+ data->regmap = regmap;
if (ACPI_HANDLE(dev))
name = bmc150_accel_match_acpi_device(dev, &chip_id);
@@ -1664,9 +1643,7 @@ static int bmc150_accel_probe(struct i2c_client *client,
if (ret)
goto err_buffer_cleanup;
- if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) ||
- i2c_check_functionality(client->adapter,
- I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
+ if (block_supported) {
indio_dev->modes |= INDIO_BUFFER_SOFTWARE;
indio_dev->info = &bmc150_accel_info_fifo;
indio_dev->buffer->attrs = bmc150_accel_fifo_attributes;
@@ -1675,7 +1652,7 @@ static int bmc150_accel_probe(struct i2c_client *client,
ret = iio_device_register(indio_dev);
if (ret < 0) {
- dev_err(data->dev, "Unable to register iio device\n");
+ dev_err(dev, "Unable to register iio device\n");
goto err_trigger_unregister;
}
@@ -1698,10 +1675,11 @@ err_buffer_cleanup:
return ret;
}
+EXPORT_SYMBOL_GPL(bmc150_accel_core_probe);
-static int bmc150_accel_remove(struct i2c_client *client)
+int bmc150_accel_core_remove(struct device *dev)
{
- struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct bmc150_accel_data *data = iio_priv(indio_dev);
pm_runtime_disable(data->dev);
@@ -1720,6 +1698,7 @@ static int bmc150_accel_remove(struct i2c_client *client)
return 0;
}
+EXPORT_SYMBOL_GPL(bmc150_accel_core_remove);
#ifdef CONFIG_PM_SLEEP
static int bmc150_accel_suspend(struct device *dev)
@@ -1790,48 +1769,8 @@ static int bmc150_accel_runtime_resume(struct device *dev)
}
#endif
-static const struct dev_pm_ops bmc150_accel_pm_ops = {
+const struct dev_pm_ops bmc150_accel_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(bmc150_accel_suspend, bmc150_accel_resume)
SET_RUNTIME_PM_OPS(bmc150_accel_runtime_suspend,
bmc150_accel_runtime_resume, NULL)
};
-
-static const struct acpi_device_id bmc150_accel_acpi_match[] = {
- {"BSBA0150", bmc150},
- {"BMC150A", bmc150},
- {"BMI055A", bmi055},
- {"BMA0255", bma255},
- {"BMA250E", bma250e},
- {"BMA222E", bma222e},
- {"BMA0280", bma280},
- { },
-};
-MODULE_DEVICE_TABLE(acpi, bmc150_accel_acpi_match);
-
-static const struct i2c_device_id bmc150_accel_id[] = {
- {"bmc150_accel", bmc150},
- {"bmi055_accel", bmi055},
- {"bma255", bma255},
- {"bma250e", bma250e},
- {"bma222e", bma222e},
- {"bma280", bma280},
- {}
-};
-
-MODULE_DEVICE_TABLE(i2c, bmc150_accel_id);
-
-static struct i2c_driver bmc150_accel_driver = {
- .driver = {
- .name = BMC150_ACCEL_DRV_NAME,
- .acpi_match_table = ACPI_PTR(bmc150_accel_acpi_match),
- .pm = &bmc150_accel_pm_ops,
- },
- .probe = bmc150_accel_probe,
- .remove = bmc150_accel_remove,
- .id_table = bmc150_accel_id,
-};
-module_i2c_driver(bmc150_accel_driver);
-
-MODULE_AUTHOR("Srinivas Pandruvada <[email protected]>");
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("BMC150 accelerometer driver");
diff --git a/drivers/iio/accel/bmc150-accel-i2c.c b/drivers/iio/accel/bmc150-accel-i2c.c
new file mode 100644
index 000000000000..7e036e2eb077
--- /dev/null
+++ b/drivers/iio/accel/bmc150-accel-i2c.c
@@ -0,0 +1,101 @@
+/*
+ * 3-axis accelerometer driver supporting following I2C Bosch-Sensortec chips:
+ * - BMC150
+ * - BMI055
+ * - BMA255
+ * - BMA250E
+ * - BMA222E
+ * - BMA280
+ *
+ * Copyright (c) 2014, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/device.h>
+#include <linux/mod_devicetable.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/acpi.h>
+#include <linux/regmap.h>
+
+#include "bmc150-accel.h"
+
+static const struct regmap_config bmc150_i2c_regmap_conf = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .use_single_rw = true,
+ .cache_type = REGCACHE_NONE,
+};
+
+static int bmc150_accel_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct regmap *regmap;
+ bool block_supported =
+ i2c_check_functionality(client->adapter, I2C_FUNC_I2C) ||
+ i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK);
+
+ regmap = devm_regmap_init_i2c(client, &bmc150_i2c_regmap_conf);
+ if (IS_ERR(regmap)) {
+ dev_err(&client->dev, "Failed to initialize i2c regmap\n");
+ return PTR_ERR(regmap);
+ }
+
+ return bmc150_accel_core_probe(&client->dev, regmap, client->irq,
+ id->name, id->driver_data,
+ block_supported);
+}
+
+static int bmc150_accel_remove(struct i2c_client *client)
+{
+ return bmc150_accel_core_remove(&client->dev);
+}
+
+static const struct acpi_device_id bmc150_accel_acpi_match[] = {
+ {"BSBA0150", bmc150},
+ {"BMC150A", bmc150},
+ {"BMI055A", bmi055},
+ {"BMA0255", bma255},
+ {"BMA250E", bma250e},
+ {"BMA222E", bma222e},
+ {"BMA0280", bma280},
+ { },
+};
+MODULE_DEVICE_TABLE(acpi, bmc150_accel_acpi_match);
+
+static const struct i2c_device_id bmc150_accel_id[] = {
+ {"bmc150_accel", bmc150},
+ {"bmi055_accel", bmi055},
+ {"bma255", bma255},
+ {"bma250e", bma250e},
+ {"bma222e", bma222e},
+ {"bma280", bma280},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, bmc150_accel_id);
+
+static struct i2c_driver bmc150_accel_driver = {
+ .driver = {
+ .name = "bmc150_accel_i2c",
+ .acpi_match_table = ACPI_PTR(bmc150_accel_acpi_match),
+ .pm = &bmc150_accel_pm_ops,
+ },
+ .probe = bmc150_accel_probe,
+ .remove = bmc150_accel_remove,
+ .id_table = bmc150_accel_id,
+};
+module_i2c_driver(bmc150_accel_driver);
+
+MODULE_AUTHOR("Srinivas Pandruvada <[email protected]>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("BMC150 I2C accelerometer driver");
diff --git a/drivers/iio/accel/bmc150-accel.h b/drivers/iio/accel/bmc150-accel.h
new file mode 100644
index 000000000000..988b57573d0c
--- /dev/null
+++ b/drivers/iio/accel/bmc150-accel.h
@@ -0,0 +1,21 @@
+#ifndef _BMC150_ACCEL_H_
+#define _BMC150_ACCEL_H_
+
+struct regmap;
+
+enum {
+ bmc150,
+ bmi055,
+ bma255,
+ bma250e,
+ bma222e,
+ bma280,
+};
+
+int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq,
+ const char *name, int chip_id,
+ bool block_supported);
+int bmc150_accel_core_remove(struct device *dev);
+extern const struct dev_pm_ops bmc150_accel_pm_ops;
+
+#endif /* _BMC150_ACCEL_H_ */
--
2.4.6
Add a simple SPI driver which initializes the spi regmap for the bmc150
core driver.
Signed-off-by: Markus Pargmann <[email protected]>
---
drivers/iio/accel/Kconfig | 10 +++++
drivers/iio/accel/Makefile | 1 +
drivers/iio/accel/bmc150-accel-spi.c | 86 ++++++++++++++++++++++++++++++++++++
3 files changed, 97 insertions(+)
create mode 100644 drivers/iio/accel/bmc150-accel-spi.c
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
index c63e981c38ff..bdb42069a767 100644
--- a/drivers/iio/accel/Kconfig
+++ b/drivers/iio/accel/Kconfig
@@ -40,6 +40,16 @@ config BMC150_ACCEL_I2C
Say yes here to build support for I2C communication with the
mentioned accelerometer.
+config BMC150_ACCEL_SPI
+ tristate "SPI support"
+ depends on SPI
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+ select REGMAP_SPI
+ help
+ Say yes here to build support for SPI communication with the
+ mentioned accelerometer.
+
endif
config HID_SENSOR_ACCEL_3D
diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile
index 5ef8bdbad092..e579e93bf022 100644
--- a/drivers/iio/accel/Makefile
+++ b/drivers/iio/accel/Makefile
@@ -6,6 +6,7 @@
obj-$(CONFIG_BMA180) += bma180.o
obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o
obj-$(CONFIG_BMC150_ACCEL_I2C) += bmc150-accel-i2c.o
+obj-$(CONFIG_BMC150_ACCEL_SPI) += bmc150-accel-spi.o
obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o
obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o
obj-$(CONFIG_KXSD9) += kxsd9.o
diff --git a/drivers/iio/accel/bmc150-accel-spi.c b/drivers/iio/accel/bmc150-accel-spi.c
new file mode 100644
index 000000000000..c13fd2aa5f34
--- /dev/null
+++ b/drivers/iio/accel/bmc150-accel-spi.c
@@ -0,0 +1,86 @@
+/*
+ * 3-axis accelerometer driver supporting following I2C Bosch-Sensortec chips:
+ * - BMC150
+ * - BMI055
+ * - BMA255
+ * - BMA250E
+ * - BMA222E
+ * - BMA280
+ *
+ * Copyright (c) 2014, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/device.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/acpi.h>
+#include <linux/regmap.h>
+#include <linux/spi/spi.h>
+
+#include "bmc150-accel.h"
+
+static const struct regmap_config bmc150_spi_regmap_conf = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 0x3f,
+
+ .use_single_rw = false,
+ .cache_type = REGCACHE_NONE,
+};
+
+static int bmc150_accel_probe(struct spi_device *spi)
+{
+ struct regmap *regmap;
+ const struct spi_device_id *id = spi_get_device_id(spi);
+
+ regmap = devm_regmap_init_spi(spi, &bmc150_spi_regmap_conf);
+ if (IS_ERR(regmap)) {
+ dev_err(&spi->dev, "Failed to initialize spi regmap\n");
+ return PTR_ERR(regmap);
+ }
+
+ return bmc150_accel_core_probe(&spi->dev, regmap, spi->irq,
+ id->name, id->driver_data, true);
+}
+
+static int bmc150_accel_remove(struct spi_device *spi)
+{
+ return bmc150_accel_core_remove(&spi->dev);
+}
+
+static const struct spi_device_id bmc150_accel_id[] = {
+ {"bmc150_accel", bmc150},
+ {"bmi055_accel", bmi055},
+ {"bma255", bma255},
+ {"bma250e", bma250e},
+ {"bma222e", bma222e},
+ {"bma280", bma280},
+ {}
+};
+
+MODULE_DEVICE_TABLE(spi, bmc150_accel_id);
+
+static struct spi_driver bmc150_accel_driver = {
+ .driver = {
+ .name = "bmc150_accel_spi",
+ .acpi_match_table = ACPI_PTR(bmc150_accel_acpi_match),
+ .pm = &bmc150_accel_pm_ops,
+ },
+ .probe = bmc150_accel_probe,
+ .remove = bmc150_accel_remove,
+ .id_table = bmc150_accel_id,
+};
+module_spi_driver(bmc150_accel_driver);
+
+MODULE_AUTHOR("Markus Pargmann <[email protected]>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("BMC150 SPI accelerometer driver");
--
2.4.6
On Wed, Aug 12, 2015 at 12:12:27PM +0200, Markus Pargmann wrote:
> Regmap does not support 64bit. The ival that is used to write the 64bit
> data to, is unsigned int and can't hold 64bit. _regmap_write also just
> supports unsigend int.
What makes you say that unsigned int can't hold 64 bit? An architecture
can have 64 bit ints if it likes.
Hi Markus,
On Wed, Aug 12, 2015 at 6:12 PM, Markus Pargmann <[email protected]> wrote:
>
> The implementation of regmap bus read() and write() methods are
> optional. Therefore we have to handle busses which do not have these
> functions. If raw read() and write() is not supported we have to use
> reg_read and reg_write always.
>
> This patch sets use_single_rw if read() or write() is not set.
>
> Signed-off-by: Markus Pargmann <[email protected]>
> ---
> drivers/base/regmap/regmap.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
> index f98bd5bf5c62..35ad3783da70 100644
> --- a/drivers/base/regmap/regmap.c
> +++ b/drivers/base/regmap/regmap.c
> @@ -573,7 +573,7 @@ struct regmap *regmap_init(struct device *dev,
> map->reg_stride = config->reg_stride;
> else
> map->reg_stride = 1;
> - map->use_single_rw = config->use_single_rw;
> + map->use_single_rw = config->use_single_rw || !bus->read || !bus->write;
What if bus is NULL?
-Dan
> map->can_multi_write = config->can_multi_write;
> map->dev = dev;
> map->bus = bus;
> --
> 2.4.6
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
On Wed, Aug 12, 2015 at 12:12:25PM +0200, Markus Pargmann wrote:
> Hi,
>
> this series was created to add SPI support to the bmc150 accelerometer driver.
> To not add any regressions, I had to add some infrastructure that allows to use
> regmap with busses that do limit the size of transfers (block smbus). I hope
> this is sufficient to not break anything.
This is a really big series but looking at at least the initial patches
there's a lot of unrelated cleanups mixed in with it. Please don't do
this, send things like cleanups separately so that your series is
focused on the relevant topic. This makes things much easier to work
with.
On Wed, Aug 12, 2015 at 12:12:29PM +0200, Markus Pargmann wrote:
> It is not obvious why format initialization is skipped here. format
> functions are used for example in regmap_bulk_read even if bus is not
> set. So they are used even if skipped here which leads to null pointer
> errors.
> This patch adds format initialization for !bus and !bus->read/write.
Format initialisation is skipped because it is not clear what the wire
format actually is if we're not using the regmap internal marshalling.
Someone needs to do a survey of what the existing users are trying to do
before changing anything here.
On Wed, Aug 12, 2015 at 11:25:50AM +0100, Mark Brown wrote:
> On Wed, Aug 12, 2015 at 12:12:27PM +0200, Markus Pargmann wrote:
> > Regmap does not support 64bit. The ival that is used to write the 64bit
> > data to, is unsigned int and can't hold 64bit. _regmap_write also just
> > supports unsigend int.
>
> What makes you say that unsigned int can't hold 64 bit? An architecture
> can have 64 bit ints if it likes.
I wasn't aware that any 64 bit architecture actually has unsigned ints
that are 64 bit in size. So wouldn't at least on x86_64 this would lead
to a compiler warning as unsigned int is 4 byte and u64 8 bytes?
Best Regards,
Markus
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
Hi,
On Wed, Aug 12, 2015 at 06:33:55PM +0800, Daniel Kurtz wrote:
> Hi Markus,
>
> On Wed, Aug 12, 2015 at 6:12 PM, Markus Pargmann <[email protected]> wrote:
> >
> > The implementation of regmap bus read() and write() methods are
> > optional. Therefore we have to handle busses which do not have these
> > functions. If raw read() and write() is not supported we have to use
> > reg_read and reg_write always.
> >
> > This patch sets use_single_rw if read() or write() is not set.
> >
> > Signed-off-by: Markus Pargmann <[email protected]>
> > ---
> > drivers/base/regmap/regmap.c | 2 +-
> > 1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
> > index f98bd5bf5c62..35ad3783da70 100644
> > --- a/drivers/base/regmap/regmap.c
> > +++ b/drivers/base/regmap/regmap.c
> > @@ -573,7 +573,7 @@ struct regmap *regmap_init(struct device *dev,
> > map->reg_stride = config->reg_stride;
> > else
> > map->reg_stride = 1;
> > - map->use_single_rw = config->use_single_rw;
> > + map->use_single_rw = config->use_single_rw || !bus->read || !bus->write;
>
> What if bus is NULL?
Yes thanks, that has to be checked.
Best Regards,
Markus
>
> -Dan
>
> > map->can_multi_write = config->can_multi_write;
> > map->dev = dev;
> > map->bus = bus;
> > --
> > 2.4.6
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> > the body of a message to [email protected]
> > More majordomo info at http://vger.kernel.org/majordomo-info.html
> > Please read the FAQ at http://www.tux.org/lkml/
>
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
On Wed, Aug 12, 2015 at 11:37:36AM +0100, Mark Brown wrote:
> On Wed, Aug 12, 2015 at 12:12:25PM +0200, Markus Pargmann wrote:
> > Hi,
> >
> > this series was created to add SPI support to the bmc150 accelerometer driver.
> > To not add any regressions, I had to add some infrastructure that allows to use
> > regmap with busses that do limit the size of transfers (block smbus). I hope
> > this is sufficient to not break anything.
>
> This is a really big series but looking at at least the initial patches
> there's a lot of unrelated cleanups mixed in with it. Please don't do
> this, send things like cleanups separately so that your series is
> focused on the relevant topic. This makes things much easier to work
> with.
Ok. I can try to separate them but there are lots of dependencies
between the patches and most of them touch regmap.c so I thought it may
be better to put it in one series.
I will try my best to separate them for the next version.
Best Regards,
Markus
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
On Wed, Aug 12, 2015 at 12:12:30PM +0200, Markus Pargmann wrote:
> Currently we try to write the data without copying directly using
> bus->write() or bus->gather_write() if it exists. If one of the previous
> tries to write reported -ENOTSUPP or none of them were usable, we copy
> the data into a buffer and use bus->write().
>
> However it does not make sense to try bus->write() a second time with a
> copied buffer if it didn't work the first time.
>
> This patch restructures this if/else block to make it clear that this is
> not intended for the case where bus->write() returns -ENOTSUPP.
I'm not entirely convinced that this is an improvement. The main effect
that I'm seeing is an increase in the indentation level and there are
potential issues with the write operation being unable to work with some
kinds of memory (like restrictions about dmaing from stack or unalinged
memory for example) which mean that copying into a newly allocated
buffer may actually help. I don't think we detect any such restrictions
at the minute but the defensiveness is nice and I'd really hope that the
failed write case isn't any kind of fast path.
On Wed, Aug 12, 2015 at 12:44:36PM +0200, Markus Pargmann wrote:
> I wasn't aware that any 64 bit architecture actually has unsigned ints
> that are 64 bit in size. So wouldn't at least on x86_64 this would lead
> to a compiler warning as unsigned int is 4 byte and u64 8 bytes?
Nobody complained about warnings yet. The compiler probably shouldn't
be complaining given the casts, they're supposed to be an "I know what
I'm doing" thing. If you want to change something here it's changing
the test to be based on sizeof(unsigned int).
On Wed, Aug 12, 2015 at 12:12:31PM +0200, Markus Pargmann wrote:
> Cc: Stephen Boyd <[email protected]>
I'm not sure why you're putting this in these commit messages...
> if (!map->bus || map->use_single_rw) {
> + if (val_bytes != 1 && val_bytes != 2 && val_bytes != 4)
> + return -EINVAL;
> +
switch statement please. This also looks like a separate change to the
handling of single writes.
> + } else if (map->use_single_rw) {
> + /*
How are we ever going to fall into this else case? The first check has
an || map->use_single_rw it so if this is true then the first check will
be too so we'd never end up in this else case.
On Wed, Aug 12, 2015 at 12:12:32PM +0200, Markus Pargmann wrote:
> The implementation of regmap bus read() and write() methods are
> optional. Therefore we have to handle busses which do not have these
> functions. If raw read() and write() is not supported we have to use
> reg_read and reg_write always.
>
> This patch sets use_single_rw if read() or write() is not set.
> - map->use_single_rw = config->use_single_rw;
> + map->use_single_rw = config->use_single_rw || !bus->read || !bus->write;
This doesn't follow, we should be able to support write only or read
only buses. There are some out there.
On Wed, Aug 12, 2015 at 12:12:34PM +0200, Markus Pargmann wrote:
> @@ -1229,6 +1229,11 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
> }
> }
>
> + if (!map->bus->write && val_len == map->format.val_bytes) {
> + ret = _regmap_bus_reg_write(map, reg, *(unsigned int *)val);
> + return ret;
> + }
This is broken - you can't use a raw value as a register value. The
endianness of the device may not be the same as the endianness of the
system and you can't cast a value to unsigned int, the value may be of
any size.
> @@ -1340,7 +1345,7 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
> * send the work_buf directly, otherwise try to do a gather
> * write.
> */
> - if (val == work_val) {
> + if (val == work_val && map->bus->write) {
> ret = map->bus->write(map->bus_context, map->work_buf,
> map->format.reg_bytes +
> map->format.pad_bytes +
This appears to be another case of merging an unrelated change :(
On Wed, Aug 12, 2015 at 12:12:36PM +0200, Markus Pargmann wrote:
> + /*
> + * There are busses that do not have a read function as it is optional.
> + * Use their reg_read function instead if the requested number of bytes
> + * is correct.
> + */
> + if (!map->bus->read) {
> + /*
> + * bus_reg_read() does not support reading values that are not
> + * exactly the size of format.val_bytes
> + */
> + if (val_len != map->format.val_bytes)
> + return -EINVAL;
> + return _regmap_bus_reg_read(map, reg, val);
> + }
No, this makes no sense - if the device doesn't have a read operation
then it doesn't support a raw data stream and hence can't support raw
access sensibly. Callers that want to access a lot of registers at once
without knowing what the wire format for the device is should be using
the bulk or multi interfaces.
On Wed, Aug 12, 2015 at 12:12:37PM +0200, Markus Pargmann wrote:
> + /* if set, raw reads/writes are limited to this size */
> + size_t max_raw_io;
> +
Do this separately for read and write, there's doubtless going to be
something that has asymmetry.
> + if (!map->use_single_rw) {
> + write_count = total_bytes / map->max_raw_io;
> + write_bytes = map->max_raw_io;
We may not be able to fit a whole number of values into whatever the
constraint that the bus has is and partial values don't seem like a good
idea.
> + reg_stride *= write_bytes / val_bytes;
> + }
This is very confusing, regmap already has a concept of stride and this
isn't the same thing.
On Wed, Aug 12, 2015 at 12:12:38PM +0200, Markus Pargmann wrote:
> Signed-off-by: Markus Pargmann <[email protected]>
Your changelog doesn't mention why anything would reasonably want to use
this and...
> +size_t regmap_get_raw_io_max(struct regmap *map)
> +{
> + return map->max_raw_io;
> +}
> +EXPORT_SYMBOL_GPL(regmap_get_raw_io_max);
> +
> +/**
> + * regmap_get_raw_read_max - Get the maximum size we can read
> + *
> + * @map: Map to check.
> + */
...it is adding two functions which don't seem very symmetrically named.
> @@ -441,6 +441,8 @@ int regmap_get_max_register(struct regmap *map);
> int regmap_get_reg_stride(struct regmap *map);
> int regmap_async_complete(struct regmap *map);
> bool regmap_can_raw_write(struct regmap *map);
> +size_t regmap_get_raw_write_max(struct regmap *map);
> +size_t regmap_get_raw_io_max(struct regmap *map);
Do we want stubs here?
On Wed, Aug 12, 2015 at 12:12:39PM +0200, Markus Pargmann wrote:
> Check in regmap_raw_read() and regmap_raw_write() for correct maximum
> sizes of the operations. Return -E2BIG if this size is not supported
> because it is too big.
Why not just split the transaction up like your other changes did?
> Also this patch causes an uninitialized variable warning so it
> initializes ret (although not necessary).
That's just shutting the warning up without understanding where it came
from or why this is a good way of handling it :(
> @@ -2273,8 +2276,14 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
>
> map->lock(map->lock_arg);
>
> - if (regmap_volatile_range(map, reg, val_count) || map->cache_bypass ||
> - map->cache_type == REGCACHE_NONE) {
> + if (map->bus->read &&
This change doesn't match your commit log...
On Wed, Aug 12, 2015 at 12:12:40PM +0200, Markus Pargmann wrote:
> + if (count < 1 || count >= I2C_SMBUS_BLOCK_MAX)
> + return -EINVAL;
Elsewhere you added returns of -E2BIG if the transfer was too big, why
not do that here as well?
On Wed, Aug 12, 2015 at 12:12:42PM +0200, Markus Pargmann wrote:
> + select REGMAP
> + select REGMAP_I2C
You don't need to select regmap, only REGMAP_I2C.
On Wed, Aug 12, 2015 at 12:12:45PM +0200, Markus Pargmann wrote:
> + .use_single_rw = false,
> + .cache_type = REGCACHE_NONE,
> +};
No need to initialise defaults.
On Wed, Aug 12, 2015 at 12:10:31PM +0100, Mark Brown wrote:
> On Wed, Aug 12, 2015 at 12:12:31PM +0200, Markus Pargmann wrote:
>
> > Cc: Stephen Boyd <[email protected]>
>
> I'm not sure why you're putting this in these commit messages...
Just to not forget that Stephen should be in Cc as he introduced the
switch case which removed the code that I add here again:
f4298360a5c2 (regmap: Allow regmap_bulk_write() to work for "no-bus" regmaps)
>
> > if (!map->bus || map->use_single_rw) {
> > + if (val_bytes != 1 && val_bytes != 2 && val_bytes != 4)
> > + return -EINVAL;
> > +
>
> switch statement please. This also looks like a separate change to the
> handling of single writes.
Sorry this was a left-over of a previous arrangement. Will remove it.
>
> > + } else if (map->use_single_rw) {
> > + /*
>
> How are we ever going to fall into this else case? The first check has
> an || map->use_single_rw it so if this is true then the first check will
> be too so we'd never end up in this else case.
Oh right, seems like another leftover of rebases :-/ sorry. The above
condition should just be
if (!map->bus) {
Otherwise we fall into to this second case which is also able to handle
for example 3 byte values.
Thanks,
Markus
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
On Wed, Aug 12, 2015 at 12:20:35PM +0100, Mark Brown wrote:
> On Wed, Aug 12, 2015 at 12:12:34PM +0200, Markus Pargmann wrote:
>
> > @@ -1229,6 +1229,11 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
> > }
> > }
> >
> > + if (!map->bus->write && val_len == map->format.val_bytes) {
> > + ret = _regmap_bus_reg_write(map, reg, *(unsigned int *)val);
> > + return ret;
> > + }
>
> This is broken - you can't use a raw value as a register value. The
I am not sure what you mean here?
The register value given to _regmap_raw_write is the real register
value, not formatted differenty. This is given directly towards
bus->reg_write() which should handle the rest.
At least that's how I understood the code. For example regmap_read()
directly calls _regmap_read() which in turn calls directly
bus->reg_read() without any formating.
> endianness of the device may not be the same as the endianness of the
> system and you can't cast a value to unsigned int, the value may be of
> any size.
Yes right. On the other hand if bus->read() and bus->write() was not set
in the init method (before this patch series) no formatting functions at
all were assigned. So it was always ignored for bus->reg_read() and
bus->reg_write()?!
>
> > @@ -1340,7 +1345,7 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
> > * send the work_buf directly, otherwise try to do a gather
> > * write.
> > */
> > - if (val == work_val) {
> > + if (val == work_val && map->bus->write) {
> > ret = map->bus->write(map->bus_context, map->work_buf,
> > map->format.reg_bytes +
> > map->format.pad_bytes +
>
> This appears to be another case of merging an unrelated change :(
Yes, will fix.
Thanks,
Markus
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
On Wed, Aug 12, 2015 at 11:57:58AM +0100, Mark Brown wrote:
> On Wed, Aug 12, 2015 at 12:44:36PM +0200, Markus Pargmann wrote:
>
> > I wasn't aware that any 64 bit architecture actually has unsigned ints
> > that are 64 bit in size. So wouldn't at least on x86_64 this would lead
> > to a compiler warning as unsigned int is 4 byte and u64 8 bytes?
>
> Nobody complained about warnings yet. The compiler probably shouldn't
> be complaining given the casts, they're supposed to be an "I know what
> I'm doing" thing. If you want to change something here it's changing
> the test to be based on sizeof(unsigned int).
Ok, would work for me as well although sizeof is not a preprocessor
macro so I would probably leave it as it is. The whole regmap framework
just didn't seem to support 64bit so I thought this was just not
working.
Thanks,
Markus
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
On Wed, Aug 12, 2015 at 02:20:11PM +0200, Markus Pargmann wrote:
> On Wed, Aug 12, 2015 at 12:20:35PM +0100, Mark Brown wrote:
> > On Wed, Aug 12, 2015 at 12:12:34PM +0200, Markus Pargmann wrote:
> >
> > > @@ -1229,6 +1229,11 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
> > > }
> > > }
> > >
> > > + if (!map->bus->write && val_len == map->format.val_bytes) {
> > > + ret = _regmap_bus_reg_write(map, reg, *(unsigned int *)val);
> > > + return ret;
> > > + }
> > This is broken - you can't use a raw value as a register value. The
> I am not sure what you mean here?
> The register value given to _regmap_raw_write is the real register
> value, not formatted differenty. This is given directly towards
> bus->reg_write() which should handle the rest.
I mean the value for the register, not the register address.
> At least that's how I understood the code. For example regmap_read()
> directly calls _regmap_read() which in turn calls directly
> bus->reg_read() without any formating.
You're adding this code to regmap_raw_write() which takes raw register
values for the device, not unsigned integers.
> > endianness of the device may not be the same as the endianness of the
> > system and you can't cast a value to unsigned int, the value may be of
> > any size.
> Yes right. On the other hand if bus->read() and bus->write() was not set
> in the init method (before this patch series) no formatting functions at
> all were assigned. So it was always ignored for bus->reg_read() and
> bus->reg_write()?!
I'm not sure what the "it" you're talking about here is, sorry. There
are unsupported features in the API especially for cases that don't make
a huge amount of sense, the error handling isn't always complete. It
sounds like you might be trying to support one of these nonsensical
cases - it's not obvious what raw I/O on a device where we don't know
the raw format of the device should mean or how anything could sensibly
use that.
On Wed, Aug 12, 2015 at 12:27:07PM +0100, Mark Brown wrote:
> On Wed, Aug 12, 2015 at 12:12:36PM +0200, Markus Pargmann wrote:
>
> > + /*
> > + * There are busses that do not have a read function as it is optional.
> > + * Use their reg_read function instead if the requested number of bytes
> > + * is correct.
> > + */
> > + if (!map->bus->read) {
> > + /*
> > + * bus_reg_read() does not support reading values that are not
> > + * exactly the size of format.val_bytes
> > + */
> > + if (val_len != map->format.val_bytes)
> > + return -EINVAL;
> > + return _regmap_bus_reg_read(map, reg, val);
> > + }
>
> No, this makes no sense - if the device doesn't have a read operation
> then it doesn't support a raw data stream and hence can't support raw
> access sensibly. Callers that want to access a lot of registers at once
> without knowing what the wire format for the device is should be using
> the bulk or multi interfaces.
Yes okay. Then I will reduce this patch to the following and put it
into regmap_read() instead?
if (!map->bus->read) {
return -EINVAL;
Is -EINVAL the right thing to return or would you prefer -ENOTSUPP?
Thanks,
Markus
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
On Wed, Aug 12, 2015 at 02:28:56PM +0200, Markus Pargmann wrote:
> Ok, would work for me as well although sizeof is not a preprocessor
> macro so I would probably leave it as it is. The whole regmap framework
> just didn't seem to support 64bit so I thought this was just not
> working.
I'd expect the framework to cope with things when ints are 64 bit. We
don't try to support anything else, though.
On Wed, Aug 12, 2015 at 12:49:31PM +0100, Mark Brown wrote:
> On Wed, Aug 12, 2015 at 12:12:37PM +0200, Markus Pargmann wrote:
>
> > + /* if set, raw reads/writes are limited to this size */
> > + size_t max_raw_io;
> > +
>
> Do this separately for read and write, there's doubtless going to be
> something that has asymmetry.
Okay.
>
> > + if (!map->use_single_rw) {
> > + write_count = total_bytes / map->max_raw_io;
> > + write_bytes = map->max_raw_io;
>
> We may not be able to fit a whole number of values into whatever the
> constraint that the bus has is and partial values don't seem like a good
> idea.
Oh right. Will change the calculation so that there are no partial
values being written.
>
> > + reg_stride *= write_bytes / val_bytes;
> > + }
>
> This is very confusing, regmap already has a concept of stride and this
> isn't the same thing.
Okay, will rename it.
Thanks,
Markus
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
On Wed, Aug 12, 2015 at 12:12:35PM +0200, Markus Pargmann wrote:
> Define a fallback for busses which do not define a write() function.
> Instead we write one register at a time using reg_write().
>
> Without this patch, _regmap_raw_multi_reg_write would break as it tries
> to call bus->write() without checking if it exists before.
Why are we trying to use multi write APIs in the first place if we can't
do raw I/O?
On Wed, Aug 12, 2015 at 12:57:59PM +0100, Mark Brown wrote:
> On Wed, Aug 12, 2015 at 12:12:39PM +0200, Markus Pargmann wrote:
>
> > Check in regmap_raw_read() and regmap_raw_write() for correct maximum
> > sizes of the operations. Return -E2BIG if this size is not supported
> > because it is too big.
>
> Why not just split the transaction up like your other changes did?
My intention was to keep these raw functions as close to the actual
hardware as possible also reporting proper error values. For
transactions that are split up you could still use the bulk functions.
The actual use case is the bmc150 driver. This chip has a FIFO behind
one of its registers. At exactly that register there is no autoincrement
of the address or anything, it is just a much larger register. But you
have to read from it in bigger chunks than normal. If you read in
chunks that do not have the correct size samples from the sensor get
discarded.
>
> > Also this patch causes an uninitialized variable warning so it
> > initializes ret (although not necessary).
>
> That's just shutting the warning up without understanding where it came
> from or why this is a good way of handling it :(
Yes, will have a look if I can find the issue.
>
> > @@ -2273,8 +2276,14 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
> >
> > map->lock(map->lock_arg);
> >
> > - if (regmap_volatile_range(map, reg, val_count) || map->cache_bypass ||
> > - map->cache_type == REGCACHE_NONE) {
> > + if (map->bus->read &&
>
> This change doesn't match your commit log...
Sorry.
Thanks,
Markus
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
On Wed, Aug 12, 2015 at 12:51:36PM +0100, Mark Brown wrote:
> On Wed, Aug 12, 2015 at 12:12:38PM +0200, Markus Pargmann wrote:
> > Signed-off-by: Markus Pargmann <[email protected]>
>
> Your changelog doesn't mention why anything would reasonably want to use
> this and...
Right, this is used later in the driver code of bmc150 to find out how
much we can read from the sensor in one run.
>
> > +size_t regmap_get_raw_io_max(struct regmap *map)
> > +{
> > + return map->max_raw_io;
> > +}
> > +EXPORT_SYMBOL_GPL(regmap_get_raw_io_max);
> > +
> > +/**
> > + * regmap_get_raw_read_max - Get the maximum size we can read
> > + *
> > + * @map: Map to check.
> > + */
>
> ...it is adding two functions which don't seem very symmetrically named.
Oh, this is half of my previous version where raw_read_max and
raw_write_max where separate. Will fix it along with your comment that
these should be different values for read and write.
Thanks,
Markus
>
> > @@ -441,6 +441,8 @@ int regmap_get_max_register(struct regmap *map);
> > int regmap_get_reg_stride(struct regmap *map);
> > int regmap_async_complete(struct regmap *map);
> > bool regmap_can_raw_write(struct regmap *map);
> > +size_t regmap_get_raw_write_max(struct regmap *map);
> > +size_t regmap_get_raw_io_max(struct regmap *map);
>
> Do we want stubs here?
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
On Wed, Aug 12, 2015 at 12:59:37PM +0100, Mark Brown wrote:
> On Wed, Aug 12, 2015 at 12:12:40PM +0200, Markus Pargmann wrote:
>
> > + if (count < 1 || count >= I2C_SMBUS_BLOCK_MAX)
> > + return -EINVAL;
>
> Elsewhere you added returns of -E2BIG if the transfer was too big, why
> not do that here as well?
Sounds good to use E2BIG here as well.
Best Regards,
Markus
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
On Wed, Aug 12, 2015 at 01:01:46PM +0100, Mark Brown wrote:
> On Wed, Aug 12, 2015 at 12:12:42PM +0200, Markus Pargmann wrote:
>
> > + select REGMAP
> > + select REGMAP_I2C
>
> You don't need to select regmap, only REGMAP_I2C.
Ok, thanks, will fix.
Best Regards,
Markus
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
On Wed, Aug 12, 2015 at 01:34:06PM +0100, Mark Brown wrote:
> On Wed, Aug 12, 2015 at 02:20:11PM +0200, Markus Pargmann wrote:
> > On Wed, Aug 12, 2015 at 12:20:35PM +0100, Mark Brown wrote:
> > > On Wed, Aug 12, 2015 at 12:12:34PM +0200, Markus Pargmann wrote:
> > >
> > > > @@ -1229,6 +1229,11 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
> > > > }
> > > > }
> > > >
> > > > + if (!map->bus->write && val_len == map->format.val_bytes) {
> > > > + ret = _regmap_bus_reg_write(map, reg, *(unsigned int *)val);
> > > > + return ret;
> > > > + }
>
> > > This is broken - you can't use a raw value as a register value. The
>
> > I am not sure what you mean here?
>
> > The register value given to _regmap_raw_write is the real register
> > value, not formatted differenty. This is given directly towards
> > bus->reg_write() which should handle the rest.
>
> I mean the value for the register, not the register address.
>
> > At least that's how I understood the code. For example regmap_read()
> > directly calls _regmap_read() which in turn calls directly
> > bus->reg_read() without any formating.
>
> You're adding this code to regmap_raw_write() which takes raw register
> values for the device, not unsigned integers.
Ah yes, I see.
>
> > > endianness of the device may not be the same as the endianness of the
> > > system and you can't cast a value to unsigned int, the value may be of
> > > any size.
>
> > Yes right. On the other hand if bus->read() and bus->write() was not set
> > in the init method (before this patch series) no formatting functions at
> > all were assigned. So it was always ignored for bus->reg_read() and
> > bus->reg_write()?!
>
> I'm not sure what the "it" you're talking about here is, sorry. There
> are unsupported features in the API especially for cases that don't make
> a huge amount of sense, the error handling isn't always complete. It
> sounds like you might be trying to support one of these nonsensical
> cases - it's not obvious what raw I/O on a device where we don't know
> the raw format of the device should mean or how anything could sensibly
> use that.
The bus and the regmap user are separate. So as a regmap user, I am not
able to know if the bus the device is connected to actually supports raw
reads/writes. At least it should not fail with a null pointer when using
these functions anyway so yes error handling is missing a bit here.
Also the real use of this function is regmap_bulk_write() which always
uses _regmap_raw_write() regardless of a missing bus->write() function.
So regmap_bulk_write will fail for those as well and this should be
supported.
But it is probably better to handle this in regmap_bulk_write() and
add a simple check for bus->write() here.
Best Regards,
Markus
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
On Wed, Aug 12, 2015 at 01:35:37PM +0100, Mark Brown wrote:
> On Wed, Aug 12, 2015 at 02:28:56PM +0200, Markus Pargmann wrote:
>
> > Ok, would work for me as well although sizeof is not a preprocessor
> > macro so I would probably leave it as it is. The whole regmap framework
> > just didn't seem to support 64bit so I thought this was just not
> > working.
>
> I'd expect the framework to cope with things when ints are 64 bit. We
> don't try to support anything else, though.
For all non-busses it probably will. All the format functions are not
working for 64bit at the moment. But that's something different, also I
didn't see a bus device with 64bit yet.
Best Regards,
Markus
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
On Wed, Aug 12, 2015 at 01:39:23PM +0100, Mark Brown wrote:
> On Wed, Aug 12, 2015 at 12:12:35PM +0200, Markus Pargmann wrote:
> > Define a fallback for busses which do not define a write() function.
> > Instead we write one register at a time using reg_write().
> >
> > Without this patch, _regmap_raw_multi_reg_write would break as it tries
> > to call bus->write() without checking if it exists before.
>
> Why are we trying to use multi write APIs in the first place if we can't
> do raw I/O?
Because we may not know if the bus supports raw IO and I would prefer
if it is not necessary to know in the driver that just uses the regmap
API if the underlying bus supports it.
Sorry this patch is wrong, instead it should set can_multi_write
properly depending on the availability of map->bus->write(). The code
would already handle multi writes then.
Thanks,
Markus
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
On Wed, Aug 12, 2015 at 03:08:38PM +0200, Markus Pargmann wrote:
> On Wed, Aug 12, 2015 at 01:35:37PM +0100, Mark Brown wrote:
> > I'd expect the framework to cope with things when ints are 64 bit. We
> > don't try to support anything else, though.
> For all non-busses it probably will. All the format functions are not
> working for 64bit at the moment. But that's something different, also I
> didn't see a bus device with 64bit yet.
This is expected to be used by memory mapped devices.
Markus Pargmann schrieb am 12.08.2015 um 12:12:
> There are some fields of this struct undocumented or old. This patch
> updates the missing comments.
>
> Signed-off-by: Markus Pargmann <[email protected]>
> ---
> include/linux/regmap.h | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/include/linux/regmap.h b/include/linux/regmap.h
> index 59c55ea0f0b5..6ff83c9ddb45 100644
> --- a/include/linux/regmap.h
> +++ b/include/linux/regmap.h
> @@ -296,8 +296,11 @@ typedef void (*regmap_hw_free_context)(void *context);
> * if not implemented on a given device.
> * @async_write: Write operation which completes asynchronously, optional and
> * must serialise with respect to non-async I/O.
> + * @reg_write: Write operation for a register. Writes value to register.
> * @read: Read operation. Data is returned in the buffer used to transmit
> * data.
> + * @reg_read: Read operation for a register. Reads a value from a register.
> + * @free_conetext: Free context.
Typo: free_context
> * @async_alloc: Allocate a regmap_async() structure.
> * @read_flag_mask: Mask to be set in the top byte of the register when doing
> * a read.
> @@ -307,7 +310,6 @@ typedef void (*regmap_hw_free_context)(void *context);
> * @val_format_endian_default: Default endianness for formatted register
> * values. Used when the regmap_config specifies DEFAULT. If this is
> * DEFAULT, BIG is assumed.
> - * @async_size: Size of struct used for async work.
> */
> struct regmap_bus {
> bool fast_io;
>
On Wed, Aug 12, 2015 at 12:47:39PM +0200, Markus Pargmann wrote:
> Ok. I can try to separate them but there are lots of dependencies
> between the patches and most of them touch regmap.c so I thought it may
> be better to put it in one series.
No, just the opposite - it means there's much less structure to the
series as it just becomes a sequence of unrelated changes without
overall aim or common theme.
On Wed, Aug 12, 2015 at 02:34:12PM +0200, Markus Pargmann wrote:
> Is -EINVAL the right thing to return or would you prefer -ENOTSUPP?
-ENOTSUPP is going to be better.
On Wed, Aug 12, 2015 at 02:47:06PM +0200, Markus Pargmann wrote:
> On Wed, Aug 12, 2015 at 12:57:59PM +0100, Mark Brown wrote:
> > On Wed, Aug 12, 2015 at 12:12:39PM +0200, Markus Pargmann wrote:
> > > Check in regmap_raw_read() and regmap_raw_write() for correct maximum
> > > sizes of the operations. Return -E2BIG if this size is not supported
> > > because it is too big.
> > Why not just split the transaction up like your other changes did?
> My intention was to keep these raw functions as close to the actual
> hardware as possible also reporting proper error values. For
> transactions that are split up you could still use the bulk functions.
That's not what we do otherwise, and not what you yourself have done for
some of the other changes in the series like those around multi write.
On Wed, Aug 12, 2015 at 03:05:18PM +0200, Markus Pargmann wrote:
> On Wed, Aug 12, 2015 at 01:34:06PM +0100, Mark Brown wrote:
> > > Yes right. On the other hand if bus->read() and bus->write() was not set
> > > in the init method (before this patch series) no formatting functions at
> > > all were assigned. So it was always ignored for bus->reg_read() and
> > > bus->reg_write()?!
> > I'm not sure what the "it" you're talking about here is, sorry. There
> > are unsupported features in the API especially for cases that don't make
> > a huge amount of sense, the error handling isn't always complete. It
> > sounds like you might be trying to support one of these nonsensical
> > cases - it's not obvious what raw I/O on a device where we don't know
> > the raw format of the device should mean or how anything could sensibly
> > use that.
> The bus and the regmap user are separate. So as a regmap user, I am not
> able to know if the bus the device is connected to actually supports raw
> reads/writes. At least it should not fail with a null pointer when using
You should generally have a pretty good idea simply by knowing which
device you're working with - unless you're writing generic code you know
which device you're working with and what it's capabilities are. A
driver that doesn't know these things should never be trying to do raw
I/O, and a driver that is doing raw I/O clearly depends on having the
ability to get a bytestream to and from the device since that's what raw
I/O does.
On 12/08/15 11:12, Markus Pargmann wrote:
> Valid irqs are > 0. This patch fixes the check which fails for the new
> spi driver part if no interrupt was given.
>
> Signed-off-by: Markus Pargmann <[email protected]>
This one crossed with Octavian's patch that cleaned up all cases of this.
c176becd81843 iio: fix drivers that consider 0 as a valid IRQ in client->irq
Hence you can drop this one from the v2 of this series.
(Its amazing how many times we get multiple patches for the same issue that
has been there for ages in the same week or so!)
Jonathan
> ---
> drivers/iio/accel/bmc150-accel.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel.c
> index 4e70f51c2370..fe2d2316158f 100644
> --- a/drivers/iio/accel/bmc150-accel.c
> +++ b/drivers/iio/accel/bmc150-accel.c
> @@ -1660,10 +1660,10 @@ static int bmc150_accel_probe(struct i2c_client *client,
> return ret;
> }
>
> - if (client->irq < 0)
> + if (client->irq <= 0)
> client->irq = bmc150_accel_gpio_probe(client, data);
>
> - if (client->irq >= 0) {
> + if (client->irq > 0) {
> ret = devm_request_threaded_irq(
> &client->dev, client->irq,
> bmc150_accel_irq_handler,
>
On 12/08/15 11:12, Markus Pargmann wrote:
> This replaces all usage of direct i2c accesses with regmap accesses.
>
> Signed-off-by: Markus Pargmann <[email protected]>
Clearly there is some work needed on the earlier patches and this
might change as a result (particularly the fifo read). I'll review
as is however..
Few bits on top of what other reviews have highlighted...
Jonathan
> ---
> drivers/iio/accel/Kconfig | 2 +
> drivers/iio/accel/bmc150-accel.c | 225 +++++++++++++++++----------------------
> 2 files changed, 101 insertions(+), 126 deletions(-)
>
> diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
> index 00e7bcbdbe24..01dd03d194d1 100644
> --- a/drivers/iio/accel/Kconfig
> +++ b/drivers/iio/accel/Kconfig
> @@ -22,6 +22,8 @@ config BMC150_ACCEL
> depends on I2C
> select IIO_BUFFER
> select IIO_TRIGGERED_BUFFER
> + select REGMAP
> + select REGMAP_I2C
> help
> Say yes here to build support for the following Bosch accelerometers:
> BMC150, BMI055, BMA250E, BMA222E, BMA255, BMA280.
> diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel.c
> index fe2d2316158f..1484e956482e 100644
> --- a/drivers/iio/accel/bmc150-accel.c
> +++ b/drivers/iio/accel/bmc150-accel.c
> @@ -35,6 +35,7 @@
> #include <linux/iio/trigger.h>
> #include <linux/iio/trigger_consumer.h>
> #include <linux/iio/triggered_buffer.h>
> +#include <linux/regmap.h>
>
> #define BMC150_ACCEL_DRV_NAME "bmc150_accel"
> #define BMC150_ACCEL_IRQ_NAME "bmc150_accel_event"
> @@ -185,6 +186,8 @@ enum bmc150_accel_trigger_id {
>
> struct bmc150_accel_data {
> struct i2c_client *client;
> + struct regmap *regmap;
> + struct device *dev;
> struct bmc150_accel_interrupt interrupts[BMC150_ACCEL_INTERRUPTS];
> atomic_t active_intr;
> struct bmc150_accel_trigger triggers[BMC150_ACCEL_TRIGGERS];
> @@ -241,6 +244,14 @@ static const struct {
> {500000, BMC150_ACCEL_SLEEP_500_MS},
> {1000000, BMC150_ACCEL_SLEEP_1_SEC} };
>
> +static const struct regmap_config bmc150_i2c_regmap_conf = {
> + .reg_bits = 8,
> + .val_bits = 8,
> + .max_register = 0x3f,
> +
> + .use_single_rw = false,
> + .cache_type = REGCACHE_NONE,
> +};
>
> static int bmc150_accel_set_mode(struct bmc150_accel_data *data,
> enum bmc150_power_modes mode,
> @@ -270,8 +281,7 @@ static int bmc150_accel_set_mode(struct bmc150_accel_data *data,
>
> dev_dbg(&data->client->dev, "Set Mode bits %x\n", lpw_bits);
>
> - ret = i2c_smbus_write_byte_data(data->client,
> - BMC150_ACCEL_REG_PMU_LPW, lpw_bits);
> + ret = regmap_write(data->regmap, BMC150_ACCEL_REG_PMU_LPW, lpw_bits);
> if (ret < 0) {
> dev_err(&data->client->dev, "Error writing reg_pmu_lpw\n");
> return ret;
> @@ -289,8 +299,7 @@ static int bmc150_accel_set_bw(struct bmc150_accel_data *data, int val,
> for (i = 0; i < ARRAY_SIZE(bmc150_accel_samp_freq_table); ++i) {
> if (bmc150_accel_samp_freq_table[i].val == val &&
> bmc150_accel_samp_freq_table[i].val2 == val2) {
> - ret = i2c_smbus_write_byte_data(
> - data->client,
> + ret = regmap_write(data->regmap,
> BMC150_ACCEL_REG_PMU_BW,
> bmc150_accel_samp_freq_table[i].bw_bits);
> if (ret < 0)
> @@ -307,26 +316,19 @@ static int bmc150_accel_set_bw(struct bmc150_accel_data *data, int val,
>
> static int bmc150_accel_update_slope(struct bmc150_accel_data *data)
> {
> - int ret, val;
> + int ret;
>
> - ret = i2c_smbus_write_byte_data(data->client, BMC150_ACCEL_REG_INT_6,
> + ret = regmap_write(data->regmap, BMC150_ACCEL_REG_INT_6,
> data->slope_thres);
> if (ret < 0) {
> dev_err(&data->client->dev, "Error writing reg_int_6\n");
> return ret;
> }
>
> - ret = i2c_smbus_read_byte_data(data->client, BMC150_ACCEL_REG_INT_5);
> + ret = regmap_update_bits(data->regmap, BMC150_ACCEL_REG_INT_5,
> + BMC150_ACCEL_SLOPE_DUR_MASK, data->slope_dur);
> if (ret < 0) {
> - dev_err(&data->client->dev, "Error reading reg_int_5\n");
> - return ret;
> - }
> -
> - val = (ret & ~BMC150_ACCEL_SLOPE_DUR_MASK) | data->slope_dur;
> - ret = i2c_smbus_write_byte_data(data->client, BMC150_ACCEL_REG_INT_5,
> - val);
> - if (ret < 0) {
> - dev_err(&data->client->dev, "Error write reg_int_5\n");
> + dev_err(&data->client->dev, "Error updating reg_int_5\n");
> return ret;
> }
>
> @@ -348,17 +350,18 @@ static int bmc150_accel_any_motion_setup(struct bmc150_accel_trigger *t,
> static int bmc150_accel_chip_init(struct bmc150_accel_data *data)
> {
> int ret;
> + unsigned int val;
>
> - ret = i2c_smbus_read_byte_data(data->client, BMC150_ACCEL_REG_CHIP_ID);
> + ret = regmap_read(data->regmap, BMC150_ACCEL_REG_CHIP_ID, &val);
> if (ret < 0) {
> dev_err(&data->client->dev,
> "Error: Reading chip id\n");
> return ret;
> }
>
> - dev_dbg(&data->client->dev, "Chip Id %x\n", ret);
> - if (ret != data->chip_info->chip_id) {
> - dev_err(&data->client->dev, "Invalid chip %x\n", ret);
> + dev_dbg(&data->client->dev, "Chip Id %x\n", val);
> + if (val != data->chip_info->chip_id) {
> + dev_err(&data->client->dev, "Invalid chip %x\n", val);
> return -ENODEV;
> }
>
> @@ -372,9 +375,8 @@ static int bmc150_accel_chip_init(struct bmc150_accel_data *data)
> return ret;
>
> /* Set Default Range */
> - ret = i2c_smbus_write_byte_data(data->client,
> - BMC150_ACCEL_REG_PMU_RANGE,
> - BMC150_ACCEL_DEF_RANGE_4G);
> + ret = regmap_write(data->regmap, BMC150_ACCEL_REG_PMU_RANGE,
> + BMC150_ACCEL_DEF_RANGE_4G);
> if (ret < 0) {
> dev_err(&data->client->dev,
> "Error writing reg_pmu_range\n");
> @@ -391,10 +393,9 @@ static int bmc150_accel_chip_init(struct bmc150_accel_data *data)
> return ret;
>
> /* Set default as latched interrupts */
> - ret = i2c_smbus_write_byte_data(data->client,
> - BMC150_ACCEL_REG_INT_RST_LATCH,
> - BMC150_ACCEL_INT_MODE_LATCH_INT |
> - BMC150_ACCEL_INT_MODE_LATCH_RESET);
> + ret = regmap_write(data->regmap, BMC150_ACCEL_REG_INT_RST_LATCH,
> + BMC150_ACCEL_INT_MODE_LATCH_INT |
> + BMC150_ACCEL_INT_MODE_LATCH_RESET);
> if (ret < 0) {
> dev_err(&data->client->dev,
> "Error writing reg_int_rst_latch\n");
> @@ -527,38 +528,18 @@ static int bmc150_accel_set_interrupt(struct bmc150_accel_data *data, int i,
> return ret;
>
> /* map the interrupt to the appropriate pins */
> - ret = i2c_smbus_read_byte_data(data->client, info->map_reg);
> - if (ret < 0) {
> - dev_err(&data->client->dev, "Error reading reg_int_map\n");
> - goto out_fix_power_state;
> - }
> - if (state)
> - ret |= info->map_bitmask;
> - else
> - ret &= ~info->map_bitmask;
> -
> - ret = i2c_smbus_write_byte_data(data->client, info->map_reg,
> - ret);
> + ret = regmap_update_bits(data->regmap, info->map_reg, info->map_bitmask,
> + (state ? info->map_bitmask : 0));
> if (ret < 0) {
> - dev_err(&data->client->dev, "Error writing reg_int_map\n");
> + dev_err(&data->client->dev, "Error updating reg_int_map\n");
> goto out_fix_power_state;
> }
>
> /* enable/disable the interrupt */
> - ret = i2c_smbus_read_byte_data(data->client, info->en_reg);
> - if (ret < 0) {
> - dev_err(&data->client->dev, "Error reading reg_int_en\n");
> - goto out_fix_power_state;
> - }
> -
> - if (state)
> - ret |= info->en_bitmask;
> - else
> - ret &= ~info->en_bitmask;
> -
> - ret = i2c_smbus_write_byte_data(data->client, info->en_reg, ret);
> + ret = regmap_update_bits(data->regmap, info->en_reg, info->en_bitmask,
> + (state ? info->en_bitmask : 0));
> if (ret < 0) {
> - dev_err(&data->client->dev, "Error writing reg_int_en\n");
> + dev_err(&data->client->dev, "Error updating reg_int_en\n");
> goto out_fix_power_state;
> }
>
> @@ -581,8 +562,7 @@ static int bmc150_accel_set_scale(struct bmc150_accel_data *data, int val)
>
> for (i = 0; i < ARRAY_SIZE(data->chip_info->scale_table); ++i) {
> if (data->chip_info->scale_table[i].scale == val) {
> - ret = i2c_smbus_write_byte_data(
> - data->client,
> + ret = regmap_write(data->regmap,
> BMC150_ACCEL_REG_PMU_RANGE,
> data->chip_info->scale_table[i].reg_range);
> if (ret < 0) {
> @@ -602,16 +582,17 @@ static int bmc150_accel_set_scale(struct bmc150_accel_data *data, int val)
> static int bmc150_accel_get_temp(struct bmc150_accel_data *data, int *val)
> {
> int ret;
> + unsigned int value;
>
> mutex_lock(&data->mutex);
>
> - ret = i2c_smbus_read_byte_data(data->client, BMC150_ACCEL_REG_TEMP);
> + ret = regmap_read(data->regmap, BMC150_ACCEL_REG_TEMP, &value);
> if (ret < 0) {
> dev_err(&data->client->dev, "Error reading reg_temp\n");
> mutex_unlock(&data->mutex);
> return ret;
> }
> - *val = sign_extend32(ret, 7);
> + *val = sign_extend32(value, 7);
>
> mutex_unlock(&data->mutex);
>
> @@ -624,6 +605,7 @@ static int bmc150_accel_get_axis(struct bmc150_accel_data *data,
> {
> int ret;
> int axis = chan->scan_index;
> + unsigned int raw_val;
>
> mutex_lock(&data->mutex);
> ret = bmc150_accel_set_power_state(data, true);
> @@ -632,15 +614,15 @@ static int bmc150_accel_get_axis(struct bmc150_accel_data *data,
> return ret;
> }
>
> - ret = i2c_smbus_read_word_data(data->client,
> - BMC150_ACCEL_AXIS_TO_REG(axis));
> + ret = regmap_bulk_read(data->regmap, BMC150_ACCEL_AXIS_TO_REG(axis),
> + &raw_val, 2);
> if (ret < 0) {
> dev_err(&data->client->dev, "Error reading axis %d\n", axis);
> bmc150_accel_set_power_state(data, false);
> mutex_unlock(&data->mutex);
> return ret;
> }
> - *val = sign_extend32(ret >> chan->scan_type.shift,
> + *val = sign_extend32(raw_val >> chan->scan_type.shift,
> chan->scan_type.realbits - 1);
> ret = bmc150_accel_set_power_state(data, false);
> mutex_unlock(&data->mutex);
> @@ -904,52 +886,37 @@ static int bmc150_accel_set_watermark(struct iio_dev *indio_dev, unsigned val)
> * We must read at least one full frame in one burst, otherwise the rest of the
> * frame data is discarded.
> */
> -static int bmc150_accel_fifo_transfer(const struct i2c_client *client,
> +static int bmc150_accel_fifo_transfer(struct bmc150_accel_data *data,
> char *buffer, int samples)
> {
> int sample_length = 3 * 2;
> - u8 reg_fifo_data = BMC150_ACCEL_REG_FIFO_DATA;
> - int ret = -EIO;
> -
> - if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
> - struct i2c_msg msg[2] = {
> - {
> - .addr = client->addr,
> - .flags = 0,
> - .buf = ®_fifo_data,
> - .len = sizeof(reg_fifo_data),
> - },
> - {
> - .addr = client->addr,
> - .flags = I2C_M_RD,
> - .buf = (u8 *)buffer,
> - .len = samples * sample_length,
> - }
> - };
> + int ret;
> + int total_length = samples * sample_length;
> + int i, step;
>
> - ret = i2c_transfer(client->adapter, msg, 2);
> - if (ret != 2)
> - ret = -EIO;
> - else
> - ret = 0;
> - } else {
> - int i, step = I2C_SMBUS_BLOCK_MAX / sample_length;
> -
> - for (i = 0; i < samples * sample_length; i += step) {
> - ret = i2c_smbus_read_i2c_block_data(client,
> - reg_fifo_data, step,
> - &buffer[i]);
> - if (ret != step) {
> - ret = -EIO;
> - break;
> - }
> + ret = regmap_raw_read(data->regmap, BMC150_ACCEL_REG_FIFO_DATA, buffer,
> + total_length);
> + if (ret != -E2BIG) {
> + if (ret)
I'd invert the logic for more readability.
if (ret == -E2BIT) {
...
} else if (ret) {
...
} else {
return ret;
}
> + dev_err(data->dev, "Error transferring data from fifo\n");
> + return ret;
> + }
>
> - ret = 0;
> - }
> + /*
> + * Seems we have a bus with size limitation so we have to execute
> + * multiple reads
> + */
Can we not just query this in advance before going through the previous
failed call? THat would be cleaner to my mind.
> + step = regmap_get_raw_io_max(data->regmap) / sample_length;
> + for (i = -1; i < samples * sample_length; i += step) {
> + ret = regmap_raw_read(data->regmap, BMC150_ACCEL_REG_FIFO_DATA,
> + &buffer[i], step);
umm. Can't say I like the negative index into buffer. Why is it
necessary?
> + if (ret)
> + break;
> }
>
> if (ret)
> - dev_err(&client->dev, "Error transferring data from fifo\n");
> + dev_err(data->dev, "Error transferring data from fifo in single steps of %zu\n",
multiple steps of %zu perhaps?
> + step);
>
> return ret;
> }
> @@ -963,14 +930,15 @@ static int __bmc150_accel_fifo_flush(struct iio_dev *indio_dev,
> u16 buffer[BMC150_ACCEL_FIFO_LENGTH * 3];
> int64_t tstamp;
> uint64_t sample_period;
> - ret = i2c_smbus_read_byte_data(data->client,
> - BMC150_ACCEL_REG_FIFO_STATUS);
> + unsigned int val;
> +
> + ret = regmap_read(data->regmap, BMC150_ACCEL_REG_FIFO_STATUS, &val);
> if (ret < 0) {
> dev_err(&data->client->dev, "Error reading reg_fifo_status\n");
> return ret;
> }
>
> - count = ret & 0x7F;
> + count = val & 0x7F;
>
> if (!count)
> return 0;
> @@ -1009,7 +977,7 @@ static int __bmc150_accel_fifo_flush(struct iio_dev *indio_dev,
> if (samples && count > samples)
> count = samples;
>
> - ret = bmc150_accel_fifo_transfer(data->client, (u8 *)buffer, count);
> + ret = bmc150_accel_fifo_transfer(data, (u8 *)buffer, count);
> if (ret)
> return ret;
>
> @@ -1206,17 +1174,19 @@ static irqreturn_t bmc150_accel_trigger_handler(int irq, void *p)
> struct iio_dev *indio_dev = pf->indio_dev;
> struct bmc150_accel_data *data = iio_priv(indio_dev);
> int bit, ret, i = 0;
> + unsigned int raw_val;
>
> mutex_lock(&data->mutex);
> for_each_set_bit(bit, indio_dev->active_scan_mask,
> indio_dev->masklength) {
> - ret = i2c_smbus_read_word_data(data->client,
> - BMC150_ACCEL_AXIS_TO_REG(bit));
> + ret = regmap_bulk_read(data->regmap,
> + BMC150_ACCEL_AXIS_TO_REG(bit), &raw_val,
> + 2);
Is using a variable on the stack not going to cause issues when we add
SPI? (cacheline dma requirements).
> if (ret < 0) {
> mutex_unlock(&data->mutex);
> goto err_read;
> }
> - data->buffer[i++] = ret;
> + data->buffer[i++] = raw_val;
> }
> mutex_unlock(&data->mutex);
>
> @@ -1240,10 +1210,9 @@ static int bmc150_accel_trig_try_reen(struct iio_trigger *trig)
>
> mutex_lock(&data->mutex);
> /* clear any latched interrupt */
> - ret = i2c_smbus_write_byte_data(data->client,
> - BMC150_ACCEL_REG_INT_RST_LATCH,
> - BMC150_ACCEL_INT_MODE_LATCH_INT |
> - BMC150_ACCEL_INT_MODE_LATCH_RESET);
> + ret = regmap_write(data->regmap, BMC150_ACCEL_REG_INT_RST_LATCH,
> + BMC150_ACCEL_INT_MODE_LATCH_INT |
> + BMC150_ACCEL_INT_MODE_LATCH_RESET);
> mutex_unlock(&data->mutex);
> if (ret < 0) {
> dev_err(&data->client->dev,
> @@ -1300,34 +1269,34 @@ static int bmc150_accel_handle_roc_event(struct iio_dev *indio_dev)
> struct bmc150_accel_data *data = iio_priv(indio_dev);
> int dir;
> int ret;
> + unsigned int val;
>
> - ret = i2c_smbus_read_byte_data(data->client,
> - BMC150_ACCEL_REG_INT_STATUS_2);
> + ret = regmap_read(data->regmap, BMC150_ACCEL_REG_INT_STATUS_2, &val);
> if (ret < 0) {
> dev_err(&data->client->dev, "Error reading reg_int_status_2\n");
> return ret;
> }
>
> - if (ret & BMC150_ACCEL_ANY_MOTION_BIT_SIGN)
> + if (val & BMC150_ACCEL_ANY_MOTION_BIT_SIGN)
> dir = IIO_EV_DIR_FALLING;
> else
> dir = IIO_EV_DIR_RISING;
>
> - if (ret & BMC150_ACCEL_ANY_MOTION_BIT_X)
> + if (val & BMC150_ACCEL_ANY_MOTION_BIT_X)
> iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL,
> 0,
> IIO_MOD_X,
> IIO_EV_TYPE_ROC,
> dir),
> data->timestamp);
> - if (ret & BMC150_ACCEL_ANY_MOTION_BIT_Y)
> + if (val & BMC150_ACCEL_ANY_MOTION_BIT_Y)
> iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL,
> 0,
> IIO_MOD_Y,
> IIO_EV_TYPE_ROC,
> dir),
> data->timestamp);
> - if (ret & BMC150_ACCEL_ANY_MOTION_BIT_Z)
> + if (val & BMC150_ACCEL_ANY_MOTION_BIT_Z)
> iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL,
> 0,
> IIO_MOD_Z,
> @@ -1360,10 +1329,9 @@ static irqreturn_t bmc150_accel_irq_thread_handler(int irq, void *private)
> }
>
> if (ack) {
> - ret = i2c_smbus_write_byte_data(data->client,
> - BMC150_ACCEL_REG_INT_RST_LATCH,
> - BMC150_ACCEL_INT_MODE_LATCH_INT |
> - BMC150_ACCEL_INT_MODE_LATCH_RESET);
> + ret = regmap_write(data->regmap, BMC150_ACCEL_REG_INT_RST_LATCH,
> + BMC150_ACCEL_INT_MODE_LATCH_INT |
> + BMC150_ACCEL_INT_MODE_LATCH_RESET);
> if (ret)
> dev_err(&data->client->dev, "Error writing reg_int_rst_latch\n");
> ret = IRQ_HANDLED;
> @@ -1516,7 +1484,7 @@ static int bmc150_accel_fifo_set_mode(struct bmc150_accel_data *data)
> u8 reg = BMC150_ACCEL_REG_FIFO_CONFIG1;
> int ret;
>
> - ret = i2c_smbus_write_byte_data(data->client, reg, data->fifo_mode);
> + ret = regmap_write(data->regmap, reg, data->fifo_mode);
> if (ret < 0) {
> dev_err(&data->client->dev, "Error writing reg_fifo_config1\n");
> return ret;
> @@ -1525,9 +1493,8 @@ static int bmc150_accel_fifo_set_mode(struct bmc150_accel_data *data)
> if (!data->fifo_mode)
> return 0;
>
> - ret = i2c_smbus_write_byte_data(data->client,
> - BMC150_ACCEL_REG_FIFO_CONFIG0,
> - data->watermark);
> + ret = regmap_write(data->regmap, BMC150_ACCEL_REG_FIFO_CONFIG0,
> + data->watermark);
> if (ret < 0)
> dev_err(&data->client->dev, "Error writing reg_fifo_config0\n");
>
> @@ -1627,6 +1594,13 @@ static int bmc150_accel_probe(struct i2c_client *client,
> data = iio_priv(indio_dev);
> i2c_set_clientdata(client, indio_dev);
> data->client = client;
> + data->dev = &client->dev;
> +
> + data->regmap = devm_regmap_init_i2c(client, &bmc150_i2c_regmap_conf);
> + if (IS_ERR(data->regmap)) {
> + dev_err(&client->dev, "Failed to initialize i2c regmap\n");
> + return PTR_ERR(data->regmap);
> + }
>
> if (id) {
> name = id->name;
> @@ -1680,9 +1654,8 @@ static int bmc150_accel_probe(struct i2c_client *client,
> * want to use latch mode when we can to prevent interrupt
> * flooding.
> */
> - ret = i2c_smbus_write_byte_data(data->client,
> - BMC150_ACCEL_REG_INT_RST_LATCH,
> - BMC150_ACCEL_INT_MODE_LATCH_RESET);
> + ret = regmap_write(data->regmap, BMC150_ACCEL_REG_INT_RST_LATCH,
> + BMC150_ACCEL_INT_MODE_LATCH_RESET);
> if (ret < 0) {
> dev_err(&data->client->dev, "Error writing reg_int_rst_latch\n");
> goto err_buffer_cleanup;
>
On 12/08/15 11:12, Markus Pargmann wrote:
> i2c_client struct is now only used for debugging output. We can use the
> device struct as well so we can remove all struct i2c_client usage.
>
> Signed-off-by: Markus Pargmann <[email protected]>
This one looks fine to me.
Acked-by: Jonathan Cameron <[email protected]>
Ideally these bmc150 patches should also get a look from Srinivas
before merging however (and testing given I'm guessing you don't have
all the parts!)
Jonathan
> ---
> drivers/iio/accel/bmc150-accel.c | 120 +++++++++++++++++++--------------------
> 1 file changed, 58 insertions(+), 62 deletions(-)
>
> diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel.c
> index 1484e956482e..d75e1b0aa7e9 100644
> --- a/drivers/iio/accel/bmc150-accel.c
> +++ b/drivers/iio/accel/bmc150-accel.c
> @@ -185,9 +185,9 @@ enum bmc150_accel_trigger_id {
> };
>
> struct bmc150_accel_data {
> - struct i2c_client *client;
> struct regmap *regmap;
> struct device *dev;
> + int irq;
> struct bmc150_accel_interrupt interrupts[BMC150_ACCEL_INTERRUPTS];
> atomic_t active_intr;
> struct bmc150_accel_trigger triggers[BMC150_ACCEL_TRIGGERS];
> @@ -279,11 +279,11 @@ static int bmc150_accel_set_mode(struct bmc150_accel_data *data,
> lpw_bits = mode << BMC150_ACCEL_PMU_MODE_SHIFT;
> lpw_bits |= (dur_val << BMC150_ACCEL_PMU_BIT_SLEEP_DUR_SHIFT);
>
> - dev_dbg(&data->client->dev, "Set Mode bits %x\n", lpw_bits);
> + dev_dbg(data->dev, "Set Mode bits %x\n", lpw_bits);
>
> ret = regmap_write(data->regmap, BMC150_ACCEL_REG_PMU_LPW, lpw_bits);
> if (ret < 0) {
> - dev_err(&data->client->dev, "Error writing reg_pmu_lpw\n");
> + dev_err(data->dev, "Error writing reg_pmu_lpw\n");
> return ret;
> }
>
> @@ -321,18 +321,18 @@ static int bmc150_accel_update_slope(struct bmc150_accel_data *data)
> ret = regmap_write(data->regmap, BMC150_ACCEL_REG_INT_6,
> data->slope_thres);
> if (ret < 0) {
> - dev_err(&data->client->dev, "Error writing reg_int_6\n");
> + dev_err(data->dev, "Error writing reg_int_6\n");
> return ret;
> }
>
> ret = regmap_update_bits(data->regmap, BMC150_ACCEL_REG_INT_5,
> BMC150_ACCEL_SLOPE_DUR_MASK, data->slope_dur);
> if (ret < 0) {
> - dev_err(&data->client->dev, "Error updating reg_int_5\n");
> + dev_err(data->dev, "Error updating reg_int_5\n");
> return ret;
> }
>
> - dev_dbg(&data->client->dev, "%s: %x %x\n", __func__, data->slope_thres,
> + dev_dbg(data->dev, "%s: %x %x\n", __func__, data->slope_thres,
> data->slope_dur);
>
> return ret;
> @@ -354,14 +354,14 @@ static int bmc150_accel_chip_init(struct bmc150_accel_data *data)
>
> ret = regmap_read(data->regmap, BMC150_ACCEL_REG_CHIP_ID, &val);
> if (ret < 0) {
> - dev_err(&data->client->dev,
> + dev_err(data->dev,
> "Error: Reading chip id\n");
> return ret;
> }
>
> - dev_dbg(&data->client->dev, "Chip Id %x\n", val);
> + dev_dbg(data->dev, "Chip Id %x\n", val);
> if (val != data->chip_info->chip_id) {
> - dev_err(&data->client->dev, "Invalid chip %x\n", val);
> + dev_err(data->dev, "Invalid chip %x\n", val);
> return -ENODEV;
> }
>
> @@ -378,8 +378,7 @@ static int bmc150_accel_chip_init(struct bmc150_accel_data *data)
> ret = regmap_write(data->regmap, BMC150_ACCEL_REG_PMU_RANGE,
> BMC150_ACCEL_DEF_RANGE_4G);
> if (ret < 0) {
> - dev_err(&data->client->dev,
> - "Error writing reg_pmu_range\n");
> + dev_err(data->dev, "Error writing reg_pmu_range\n");
> return ret;
> }
>
> @@ -397,7 +396,7 @@ static int bmc150_accel_chip_init(struct bmc150_accel_data *data)
> BMC150_ACCEL_INT_MODE_LATCH_INT |
> BMC150_ACCEL_INT_MODE_LATCH_RESET);
> if (ret < 0) {
> - dev_err(&data->client->dev,
> + dev_err(data->dev,
> "Error writing reg_int_rst_latch\n");
> return ret;
> }
> @@ -439,16 +438,16 @@ static int bmc150_accel_set_power_state(struct bmc150_accel_data *data, bool on)
> int ret;
>
> if (on)
> - ret = pm_runtime_get_sync(&data->client->dev);
> + ret = pm_runtime_get_sync(data->dev);
> else {
> - pm_runtime_mark_last_busy(&data->client->dev);
> - ret = pm_runtime_put_autosuspend(&data->client->dev);
> + pm_runtime_mark_last_busy(data->dev);
> + ret = pm_runtime_put_autosuspend(data->dev);
> }
> if (ret < 0) {
> - dev_err(&data->client->dev,
> + dev_err(data->dev,
> "Failed: bmc150_accel_set_power_state for %d\n", on);
> if (on)
> - pm_runtime_put_noidle(&data->client->dev);
> + pm_runtime_put_noidle(data->dev);
>
> return ret;
> }
> @@ -531,7 +530,7 @@ static int bmc150_accel_set_interrupt(struct bmc150_accel_data *data, int i,
> ret = regmap_update_bits(data->regmap, info->map_reg, info->map_bitmask,
> (state ? info->map_bitmask : 0));
> if (ret < 0) {
> - dev_err(&data->client->dev, "Error updating reg_int_map\n");
> + dev_err(data->dev, "Error updating reg_int_map\n");
> goto out_fix_power_state;
> }
>
> @@ -539,7 +538,7 @@ static int bmc150_accel_set_interrupt(struct bmc150_accel_data *data, int i,
> ret = regmap_update_bits(data->regmap, info->en_reg, info->en_bitmask,
> (state ? info->en_bitmask : 0));
> if (ret < 0) {
> - dev_err(&data->client->dev, "Error updating reg_int_en\n");
> + dev_err(data->dev, "Error updating reg_int_en\n");
> goto out_fix_power_state;
> }
>
> @@ -566,7 +565,7 @@ static int bmc150_accel_set_scale(struct bmc150_accel_data *data, int val)
> BMC150_ACCEL_REG_PMU_RANGE,
> data->chip_info->scale_table[i].reg_range);
> if (ret < 0) {
> - dev_err(&data->client->dev,
> + dev_err(data->dev,
> "Error writing pmu_range\n");
> return ret;
> }
> @@ -588,7 +587,7 @@ static int bmc150_accel_get_temp(struct bmc150_accel_data *data, int *val)
>
> ret = regmap_read(data->regmap, BMC150_ACCEL_REG_TEMP, &value);
> if (ret < 0) {
> - dev_err(&data->client->dev, "Error reading reg_temp\n");
> + dev_err(data->dev, "Error reading reg_temp\n");
> mutex_unlock(&data->mutex);
> return ret;
> }
> @@ -617,7 +616,7 @@ static int bmc150_accel_get_axis(struct bmc150_accel_data *data,
> ret = regmap_bulk_read(data->regmap, BMC150_ACCEL_AXIS_TO_REG(axis),
> &raw_val, 2);
> if (ret < 0) {
> - dev_err(&data->client->dev, "Error reading axis %d\n", axis);
> + dev_err(data->dev, "Error reading axis %d\n", axis);
> bmc150_accel_set_power_state(data, false);
> mutex_unlock(&data->mutex);
> return ret;
> @@ -934,7 +933,7 @@ static int __bmc150_accel_fifo_flush(struct iio_dev *indio_dev,
>
> ret = regmap_read(data->regmap, BMC150_ACCEL_REG_FIFO_STATUS, &val);
> if (ret < 0) {
> - dev_err(&data->client->dev, "Error reading reg_fifo_status\n");
> + dev_err(data->dev, "Error reading reg_fifo_status\n");
> return ret;
> }
>
> @@ -1215,7 +1214,7 @@ static int bmc150_accel_trig_try_reen(struct iio_trigger *trig)
> BMC150_ACCEL_INT_MODE_LATCH_RESET);
> mutex_unlock(&data->mutex);
> if (ret < 0) {
> - dev_err(&data->client->dev,
> + dev_err(data->dev,
> "Error writing reg_int_rst_latch\n");
> return ret;
> }
> @@ -1273,7 +1272,7 @@ static int bmc150_accel_handle_roc_event(struct iio_dev *indio_dev)
>
> ret = regmap_read(data->regmap, BMC150_ACCEL_REG_INT_STATUS_2, &val);
> if (ret < 0) {
> - dev_err(&data->client->dev, "Error reading reg_int_status_2\n");
> + dev_err(data->dev, "Error reading reg_int_status_2\n");
> return ret;
> }
>
> @@ -1333,7 +1332,7 @@ static irqreturn_t bmc150_accel_irq_thread_handler(int irq, void *private)
> BMC150_ACCEL_INT_MODE_LATCH_INT |
> BMC150_ACCEL_INT_MODE_LATCH_RESET);
> if (ret)
> - dev_err(&data->client->dev, "Error writing reg_int_rst_latch\n");
> + dev_err(data->dev, "Error writing reg_int_rst_latch\n");
> ret = IRQ_HANDLED;
> } else {
> ret = IRQ_NONE;
> @@ -1385,17 +1384,13 @@ static const char *bmc150_accel_match_acpi_device(struct device *dev, int *data)
> return dev_name(dev);
> }
>
> -static int bmc150_accel_gpio_probe(struct i2c_client *client,
> - struct bmc150_accel_data *data)
> +static int bmc150_accel_gpio_probe(struct bmc150_accel_data *data)
> {
> struct device *dev;
> struct gpio_desc *gpio;
> int ret;
>
> - if (!client)
> - return -EINVAL;
> -
> - dev = &client->dev;
> + dev = data->dev;
>
> /* data ready gpio interrupt pin */
> gpio = devm_gpiod_get_index(dev, BMC150_ACCEL_GPIO_NAME, 0, GPIOD_IN);
> @@ -1448,7 +1443,7 @@ static int bmc150_accel_triggers_setup(struct iio_dev *indio_dev,
> for (i = 0; i < BMC150_ACCEL_TRIGGERS; i++) {
> struct bmc150_accel_trigger *t = &data->triggers[i];
>
> - t->indio_trig = devm_iio_trigger_alloc(&data->client->dev,
> + t->indio_trig = devm_iio_trigger_alloc(data->dev,
> bmc150_accel_triggers[i].name,
> indio_dev->name,
> indio_dev->id);
> @@ -1457,7 +1452,7 @@ static int bmc150_accel_triggers_setup(struct iio_dev *indio_dev,
> break;
> }
>
> - t->indio_trig->dev.parent = &data->client->dev;
> + t->indio_trig->dev.parent = data->dev;
> t->indio_trig->ops = &bmc150_accel_trigger_ops;
> t->intr = bmc150_accel_triggers[i].intr;
> t->data = data;
> @@ -1486,7 +1481,7 @@ static int bmc150_accel_fifo_set_mode(struct bmc150_accel_data *data)
>
> ret = regmap_write(data->regmap, reg, data->fifo_mode);
> if (ret < 0) {
> - dev_err(&data->client->dev, "Error writing reg_fifo_config1\n");
> + dev_err(data->dev, "Error writing reg_fifo_config1\n");
> return ret;
> }
>
> @@ -1496,7 +1491,7 @@ static int bmc150_accel_fifo_set_mode(struct bmc150_accel_data *data)
> ret = regmap_write(data->regmap, BMC150_ACCEL_REG_FIFO_CONFIG0,
> data->watermark);
> if (ret < 0)
> - dev_err(&data->client->dev, "Error writing reg_fifo_config0\n");
> + dev_err(data->dev, "Error writing reg_fifo_config0\n");
>
> return ret;
> }
> @@ -1586,6 +1581,7 @@ static int bmc150_accel_probe(struct i2c_client *client,
> int ret;
> const char *name = NULL;
> int chip_id = 0;
> + struct device *dev;
>
> indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
> if (!indio_dev)
> @@ -1593,12 +1589,13 @@ static int bmc150_accel_probe(struct i2c_client *client,
>
> data = iio_priv(indio_dev);
> i2c_set_clientdata(client, indio_dev);
> - data->client = client;
> data->dev = &client->dev;
> + dev = &client->dev;
> + data->irq = client->irq;
>
> data->regmap = devm_regmap_init_i2c(client, &bmc150_i2c_regmap_conf);
> if (IS_ERR(data->regmap)) {
> - dev_err(&client->dev, "Failed to initialize i2c regmap\n");
> + dev_err(dev, "Failed to initialize i2c regmap\n");
> return PTR_ERR(data->regmap);
> }
>
> @@ -1607,8 +1604,8 @@ static int bmc150_accel_probe(struct i2c_client *client,
> chip_id = id->driver_data;
> }
>
> - if (ACPI_HANDLE(&client->dev))
> - name = bmc150_accel_match_acpi_device(&client->dev, &chip_id);
> + if (ACPI_HANDLE(dev))
> + name = bmc150_accel_match_acpi_device(dev, &chip_id);
>
> data->chip_info = &bmc150_accel_chip_info_tbl[chip_id];
>
> @@ -1618,7 +1615,7 @@ static int bmc150_accel_probe(struct i2c_client *client,
>
> mutex_init(&data->mutex);
>
> - indio_dev->dev.parent = &client->dev;
> + indio_dev->dev.parent = dev;
> indio_dev->channels = data->chip_info->channels;
> indio_dev->num_channels = data->chip_info->num_channels;
> indio_dev->name = name;
> @@ -1630,16 +1627,16 @@ static int bmc150_accel_probe(struct i2c_client *client,
> bmc150_accel_trigger_handler,
> &bmc150_accel_buffer_ops);
> if (ret < 0) {
> - dev_err(&client->dev, "Failed: iio triggered buffer setup\n");
> + dev_err(data->dev, "Failed: iio triggered buffer setup\n");
> return ret;
> }
>
> - if (client->irq <= 0)
> - client->irq = bmc150_accel_gpio_probe(client, data);
> + if (data->irq <= 0)
> + data->irq = bmc150_accel_gpio_probe(data);
>
> - if (client->irq > 0) {
> + if (data->irq > 0) {
> ret = devm_request_threaded_irq(
> - &client->dev, client->irq,
> + data->dev, data->irq,
> bmc150_accel_irq_handler,
> bmc150_accel_irq_thread_handler,
> IRQF_TRIGGER_RISING,
> @@ -1657,7 +1654,7 @@ static int bmc150_accel_probe(struct i2c_client *client,
> ret = regmap_write(data->regmap, BMC150_ACCEL_REG_INT_RST_LATCH,
> BMC150_ACCEL_INT_MODE_LATCH_RESET);
> if (ret < 0) {
> - dev_err(&data->client->dev, "Error writing reg_int_rst_latch\n");
> + dev_err(data->dev, "Error writing reg_int_rst_latch\n");
> goto err_buffer_cleanup;
> }
>
> @@ -1678,18 +1675,17 @@ static int bmc150_accel_probe(struct i2c_client *client,
>
> ret = iio_device_register(indio_dev);
> if (ret < 0) {
> - dev_err(&client->dev, "Unable to register iio device\n");
> + dev_err(data->dev, "Unable to register iio device\n");
> goto err_trigger_unregister;
> }
>
> - ret = pm_runtime_set_active(&client->dev);
> + ret = pm_runtime_set_active(dev);
> if (ret)
> goto err_iio_unregister;
>
> - pm_runtime_enable(&client->dev);
> - pm_runtime_set_autosuspend_delay(&client->dev,
> - BMC150_AUTO_SUSPEND_DELAY_MS);
> - pm_runtime_use_autosuspend(&client->dev);
> + pm_runtime_enable(dev);
> + pm_runtime_set_autosuspend_delay(dev, BMC150_AUTO_SUSPEND_DELAY_MS);
> + pm_runtime_use_autosuspend(dev);
>
> return 0;
>
> @@ -1708,9 +1704,9 @@ static int bmc150_accel_remove(struct i2c_client *client)
> struct iio_dev *indio_dev = i2c_get_clientdata(client);
> struct bmc150_accel_data *data = iio_priv(indio_dev);
>
> - pm_runtime_disable(&client->dev);
> - pm_runtime_set_suspended(&client->dev);
> - pm_runtime_put_noidle(&client->dev);
> + pm_runtime_disable(data->dev);
> + pm_runtime_set_suspended(data->dev);
> + pm_runtime_put_noidle(data->dev);
>
> iio_device_unregister(indio_dev);
>
> @@ -1728,7 +1724,7 @@ static int bmc150_accel_remove(struct i2c_client *client)
> #ifdef CONFIG_PM_SLEEP
> static int bmc150_accel_suspend(struct device *dev)
> {
> - struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
> + struct iio_dev *indio_dev = dev_get_drvdata(dev);
> struct bmc150_accel_data *data = iio_priv(indio_dev);
>
> mutex_lock(&data->mutex);
> @@ -1740,7 +1736,7 @@ static int bmc150_accel_suspend(struct device *dev)
>
> static int bmc150_accel_resume(struct device *dev)
> {
> - struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
> + struct iio_dev *indio_dev = dev_get_drvdata(dev);
> struct bmc150_accel_data *data = iio_priv(indio_dev);
>
> mutex_lock(&data->mutex);
> @@ -1756,11 +1752,11 @@ static int bmc150_accel_resume(struct device *dev)
> #ifdef CONFIG_PM
> static int bmc150_accel_runtime_suspend(struct device *dev)
> {
> - struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
> + struct iio_dev *indio_dev = dev_get_drvdata(dev);
> struct bmc150_accel_data *data = iio_priv(indio_dev);
> int ret;
>
> - dev_dbg(&data->client->dev, __func__);
> + dev_dbg(data->dev, __func__);
> ret = bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_SUSPEND, 0);
> if (ret < 0)
> return -EAGAIN;
> @@ -1770,12 +1766,12 @@ static int bmc150_accel_runtime_suspend(struct device *dev)
>
> static int bmc150_accel_runtime_resume(struct device *dev)
> {
> - struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
> + struct iio_dev *indio_dev = dev_get_drvdata(dev);
> struct bmc150_accel_data *data = iio_priv(indio_dev);
> int ret;
> int sleep_val;
>
> - dev_dbg(&data->client->dev, __func__);
> + dev_dbg(data->dev, __func__);
>
> ret = bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_NORMAL, 0);
> if (ret < 0)
>
On 12/08/15 11:12, Markus Pargmann wrote:
> Signed-off-by: Markus Pargmann <[email protected]>
There are a few bits in here following through from earlier
patches that I haven't bothered mentioning as you'll have fixed
them already before this split patch).
Two more bits inline. Nothing major though.
Jonathan
> ---
> drivers/iio/accel/Kconfig | 22 +++--
> drivers/iio/accel/Makefile | 3 +-
> .../accel/{bmc150-accel.c => bmc150-accel-core.c} | 95 ++++---------------
> drivers/iio/accel/bmc150-accel-i2c.c | 101 +++++++++++++++++++++
> drivers/iio/accel/bmc150-accel.h | 21 +++++
> 5 files changed, 156 insertions(+), 86 deletions(-)
> rename drivers/iio/accel/{bmc150-accel.c => bmc150-accel-core.c} (95%)
> create mode 100644 drivers/iio/accel/bmc150-accel-i2c.c
> create mode 100644 drivers/iio/accel/bmc150-accel.h
>
> diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
> index 01dd03d194d1..c63e981c38ff 100644
> --- a/drivers/iio/accel/Kconfig
> +++ b/drivers/iio/accel/Kconfig
> @@ -18,22 +18,30 @@ config BMA180
> module will be called bma180.
>
> config BMC150_ACCEL
> - tristate "Bosch BMC150 Accelerometer Driver"
> - depends on I2C
> - select IIO_BUFFER
> - select IIO_TRIGGERED_BUFFER
> + bool "Bosch BMC150 Accelerometer Driver"
> select REGMAP
> - select REGMAP_I2C
> help
> Say yes here to build support for the following Bosch accelerometers:
> BMC150, BMI055, BMA250E, BMA222E, BMA255, BMA280.
>
> - Currently this only supports the device via an i2c interface.
> -
> This is a combo module with both accelerometer and magnetometer.
> This driver is only implementing accelerometer part, which has
> its own address and register map.
This approach does lead to a proliferation of complexity (to the
person configuring the kernel build). I prefer the approach the
ST accel driver for example takes, in which the SPI or I2C drivers
are built depending on whether the relevant dependencies are present
and the core driver is selected.
>
> +if BMC150_ACCEL
> +
> +config BMC150_ACCEL_I2C
> + tristate "I2C support"
> + depends on I2C
> + select IIO_BUFFER
> + select IIO_TRIGGERED_BUFFER
> + select REGMAP_I2C
> + help
> + Say yes here to build support for I2C communication with the
> + mentioned accelerometer.
> +
> +endif
> +
> config HID_SENSOR_ACCEL_3D
> depends on HID_SENSOR_HUB
> select IIO_BUFFER
> diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile
> index ebd2675b2a02..5ef8bdbad092 100644
> --- a/drivers/iio/accel/Makefile
> +++ b/drivers/iio/accel/Makefile
> @@ -4,7 +4,8 @@
>
> # When adding new entries keep the list in alphabetical order
> obj-$(CONFIG_BMA180) += bma180.o
> -obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel.o
> +obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o
> +obj-$(CONFIG_BMC150_ACCEL_I2C) += bmc150-accel-i2c.o
> obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o
> obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o
> obj-$(CONFIG_KXSD9) += kxsd9.o
> diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel-core.c
> similarity index 95%
> rename from drivers/iio/accel/bmc150-accel.c
> rename to drivers/iio/accel/bmc150-accel-core.c
> index d75e1b0aa7e9..8cf2786dd433 100644
> --- a/drivers/iio/accel/bmc150-accel.c
> +++ b/drivers/iio/accel/bmc150-accel-core.c
> @@ -37,6 +37,8 @@
> #include <linux/iio/triggered_buffer.h>
> #include <linux/regmap.h>
>
> +#include "bmc150-accel.h"
> +
> #define BMC150_ACCEL_DRV_NAME "bmc150_accel"
> #define BMC150_ACCEL_IRQ_NAME "bmc150_accel_event"
> #define BMC150_ACCEL_GPIO_NAME "bmc150_accel_int"
> @@ -187,7 +189,6 @@ enum bmc150_accel_trigger_id {
> struct bmc150_accel_data {
> struct regmap *regmap;
> struct device *dev;
At least from how diff is listing it, looks like you've just
moved this down the struct? Why?
> - int irq;
> struct bmc150_accel_interrupt interrupts[BMC150_ACCEL_INTERRUPTS];
> atomic_t active_intr;
> struct bmc150_accel_trigger triggers[BMC150_ACCEL_TRIGGERS];
> @@ -201,6 +202,7 @@ struct bmc150_accel_data {
> int ev_enable_state;
> int64_t timestamp, old_timestamp; /* Only used in hw fifo mode. */
> const struct bmc150_accel_chip_info *chip_info;
> + int irq;
> };
>
> static const struct {
> @@ -1076,15 +1078,6 @@ static const struct iio_chan_spec bmc150_accel_channels[] =
> static const struct iio_chan_spec bma280_accel_channels[] =
> BMC150_ACCEL_CHANNELS(14);
>
> -enum {
> - bmc150,
> - bmi055,
> - bma255,
> - bma250e,
> - bma222e,
> - bma280,
> -};
> -
> static const struct bmc150_accel_chip_info bmc150_accel_chip_info_tbl[] = {
> [bmc150] = {
> .chip_id = 0xFA,
> @@ -1573,36 +1566,22 @@ static const struct iio_buffer_setup_ops bmc150_accel_buffer_ops = {
> .postdisable = bmc150_accel_buffer_postdisable,
> };
>
> -static int bmc150_accel_probe(struct i2c_client *client,
> - const struct i2c_device_id *id)
> +int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq,
> + const char *name, int chip_id, bool block_supported)
> {
> struct bmc150_accel_data *data;
> struct iio_dev *indio_dev;
> int ret;
> - const char *name = NULL;
> - int chip_id = 0;
> - struct device *dev;
>
> - indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
> + indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
> if (!indio_dev)
> return -ENOMEM;
>
> data = iio_priv(indio_dev);
> - i2c_set_clientdata(client, indio_dev);
> - data->dev = &client->dev;
> - dev = &client->dev;
> - data->irq = client->irq;
> -
> - data->regmap = devm_regmap_init_i2c(client, &bmc150_i2c_regmap_conf);
> - if (IS_ERR(data->regmap)) {
> - dev_err(dev, "Failed to initialize i2c regmap\n");
> - return PTR_ERR(data->regmap);
> - }
> -
> - if (id) {
> - name = id->name;
> - chip_id = id->driver_data;
> - }
> + dev_set_drvdata(dev, indio_dev);
> + data->dev = dev;
> + data->irq = irq;
> + data->regmap = regmap;
>
> if (ACPI_HANDLE(dev))
> name = bmc150_accel_match_acpi_device(dev, &chip_id);
> @@ -1664,9 +1643,7 @@ static int bmc150_accel_probe(struct i2c_client *client,
> if (ret)
> goto err_buffer_cleanup;
>
> - if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) ||
> - i2c_check_functionality(client->adapter,
> - I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
> + if (block_supported) {
> indio_dev->modes |= INDIO_BUFFER_SOFTWARE;
> indio_dev->info = &bmc150_accel_info_fifo;
> indio_dev->buffer->attrs = bmc150_accel_fifo_attributes;
> @@ -1675,7 +1652,7 @@ static int bmc150_accel_probe(struct i2c_client *client,
>
> ret = iio_device_register(indio_dev);
> if (ret < 0) {
> - dev_err(data->dev, "Unable to register iio device\n");
> + dev_err(dev, "Unable to register iio device\n");
> goto err_trigger_unregister;
> }
>
> @@ -1698,10 +1675,11 @@ err_buffer_cleanup:
>
> return ret;
> }
> +EXPORT_SYMBOL_GPL(bmc150_accel_core_probe);
>
> -static int bmc150_accel_remove(struct i2c_client *client)
> +int bmc150_accel_core_remove(struct device *dev)
> {
> - struct iio_dev *indio_dev = i2c_get_clientdata(client);
> + struct iio_dev *indio_dev = dev_get_drvdata(dev);
> struct bmc150_accel_data *data = iio_priv(indio_dev);
>
> pm_runtime_disable(data->dev);
> @@ -1720,6 +1698,7 @@ static int bmc150_accel_remove(struct i2c_client *client)
>
> return 0;
> }
> +EXPORT_SYMBOL_GPL(bmc150_accel_core_remove);
>
> #ifdef CONFIG_PM_SLEEP
> static int bmc150_accel_suspend(struct device *dev)
> @@ -1790,48 +1769,8 @@ static int bmc150_accel_runtime_resume(struct device *dev)
> }
> #endif
>
> -static const struct dev_pm_ops bmc150_accel_pm_ops = {
> +const struct dev_pm_ops bmc150_accel_pm_ops = {
> SET_SYSTEM_SLEEP_PM_OPS(bmc150_accel_suspend, bmc150_accel_resume)
> SET_RUNTIME_PM_OPS(bmc150_accel_runtime_suspend,
> bmc150_accel_runtime_resume, NULL)
> };
> -
> -static const struct acpi_device_id bmc150_accel_acpi_match[] = {
> - {"BSBA0150", bmc150},
> - {"BMC150A", bmc150},
> - {"BMI055A", bmi055},
> - {"BMA0255", bma255},
> - {"BMA250E", bma250e},
> - {"BMA222E", bma222e},
> - {"BMA0280", bma280},
> - { },
> -};
> -MODULE_DEVICE_TABLE(acpi, bmc150_accel_acpi_match);
> -
> -static const struct i2c_device_id bmc150_accel_id[] = {
> - {"bmc150_accel", bmc150},
> - {"bmi055_accel", bmi055},
> - {"bma255", bma255},
> - {"bma250e", bma250e},
> - {"bma222e", bma222e},
> - {"bma280", bma280},
> - {}
> -};
> -
> -MODULE_DEVICE_TABLE(i2c, bmc150_accel_id);
> -
> -static struct i2c_driver bmc150_accel_driver = {
> - .driver = {
> - .name = BMC150_ACCEL_DRV_NAME,
> - .acpi_match_table = ACPI_PTR(bmc150_accel_acpi_match),
> - .pm = &bmc150_accel_pm_ops,
> - },
> - .probe = bmc150_accel_probe,
> - .remove = bmc150_accel_remove,
> - .id_table = bmc150_accel_id,
> -};
> -module_i2c_driver(bmc150_accel_driver);
> -
> -MODULE_AUTHOR("Srinivas Pandruvada <[email protected]>");
> -MODULE_LICENSE("GPL v2");
> -MODULE_DESCRIPTION("BMC150 accelerometer driver");
> diff --git a/drivers/iio/accel/bmc150-accel-i2c.c b/drivers/iio/accel/bmc150-accel-i2c.c
> new file mode 100644
> index 000000000000..7e036e2eb077
> --- /dev/null
> +++ b/drivers/iio/accel/bmc150-accel-i2c.c
> @@ -0,0 +1,101 @@
> +/*
> + * 3-axis accelerometer driver supporting following I2C Bosch-Sensortec chips:
> + * - BMC150
> + * - BMI055
> + * - BMA255
> + * - BMA250E
> + * - BMA222E
> + * - BMA280
> + *
> + * Copyright (c) 2014, Intel Corporation.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
> + * more details.
> + */
> +
> +#include <linux/device.h>
> +#include <linux/mod_devicetable.h>
> +#include <linux/i2c.h>
> +#include <linux/module.h>
> +#include <linux/acpi.h>
> +#include <linux/regmap.h>
> +
> +#include "bmc150-accel.h"
> +
> +static const struct regmap_config bmc150_i2c_regmap_conf = {
> + .reg_bits = 8,
> + .val_bits = 8,
> +
> + .use_single_rw = true,
> + .cache_type = REGCACHE_NONE,
> +};
> +
> +static int bmc150_accel_probe(struct i2c_client *client,
> + const struct i2c_device_id *id)
> +{
> + struct regmap *regmap;
> + bool block_supported =
> + i2c_check_functionality(client->adapter, I2C_FUNC_I2C) ||
> + i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK);
> +
> + regmap = devm_regmap_init_i2c(client, &bmc150_i2c_regmap_conf);
> + if (IS_ERR(regmap)) {
> + dev_err(&client->dev, "Failed to initialize i2c regmap\n");
> + return PTR_ERR(regmap);
> + }
> +
> + return bmc150_accel_core_probe(&client->dev, regmap, client->irq,
> + id->name, id->driver_data,
> + block_supported);
> +}
> +
> +static int bmc150_accel_remove(struct i2c_client *client)
> +{
> + return bmc150_accel_core_remove(&client->dev);
> +}
> +
> +static const struct acpi_device_id bmc150_accel_acpi_match[] = {
> + {"BSBA0150", bmc150},
> + {"BMC150A", bmc150},
> + {"BMI055A", bmi055},
> + {"BMA0255", bma255},
> + {"BMA250E", bma250e},
> + {"BMA222E", bma222e},
> + {"BMA0280", bma280},
> + { },
> +};
> +MODULE_DEVICE_TABLE(acpi, bmc150_accel_acpi_match);
> +
> +static const struct i2c_device_id bmc150_accel_id[] = {
> + {"bmc150_accel", bmc150},
> + {"bmi055_accel", bmi055},
> + {"bma255", bma255},
> + {"bma250e", bma250e},
> + {"bma222e", bma222e},
> + {"bma280", bma280},
> + {}
> +};
> +
> +MODULE_DEVICE_TABLE(i2c, bmc150_accel_id);
> +
> +static struct i2c_driver bmc150_accel_driver = {
> + .driver = {
> + .name = "bmc150_accel_i2c",
> + .acpi_match_table = ACPI_PTR(bmc150_accel_acpi_match),
> + .pm = &bmc150_accel_pm_ops,
> + },
> + .probe = bmc150_accel_probe,
> + .remove = bmc150_accel_remove,
> + .id_table = bmc150_accel_id,
> +};
> +module_i2c_driver(bmc150_accel_driver);
> +
> +MODULE_AUTHOR("Srinivas Pandruvada <[email protected]>");
> +MODULE_LICENSE("GPL v2");
> +MODULE_DESCRIPTION("BMC150 I2C accelerometer driver");
> diff --git a/drivers/iio/accel/bmc150-accel.h b/drivers/iio/accel/bmc150-accel.h
> new file mode 100644
> index 000000000000..988b57573d0c
> --- /dev/null
> +++ b/drivers/iio/accel/bmc150-accel.h
> @@ -0,0 +1,21 @@
> +#ifndef _BMC150_ACCEL_H_
> +#define _BMC150_ACCEL_H_
> +
> +struct regmap;
> +
> +enum {
> + bmc150,
> + bmi055,
> + bma255,
> + bma250e,
> + bma222e,
> + bma280,
> +};
> +
> +int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq,
> + const char *name, int chip_id,
> + bool block_supported);
> +int bmc150_accel_core_remove(struct device *dev);
> +extern const struct dev_pm_ops bmc150_accel_pm_ops;
> +
> +#endif /* _BMC150_ACCEL_H_ */
>
On 12/08/15 11:12, Markus Pargmann wrote:
> Add a simple SPI driver which initializes the spi regmap for the bmc150
> core driver.
>
> Signed-off-by: Markus Pargmann <[email protected]>
1 thing inline, plus the change of kconfig approach suggested for the
previous patch.
Otherwise, looks fine to me.
Srinivas, over to you for the next version :) (unless you are feeling
enthusiastic and want to take a look at this one)
> ---
> drivers/iio/accel/Kconfig | 10 +++++
> drivers/iio/accel/Makefile | 1 +
> drivers/iio/accel/bmc150-accel-spi.c | 86 ++++++++++++++++++++++++++++++++++++
> 3 files changed, 97 insertions(+)
> create mode 100644 drivers/iio/accel/bmc150-accel-spi.c
>
> diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
> index c63e981c38ff..bdb42069a767 100644
> --- a/drivers/iio/accel/Kconfig
> +++ b/drivers/iio/accel/Kconfig
> @@ -40,6 +40,16 @@ config BMC150_ACCEL_I2C
> Say yes here to build support for I2C communication with the
> mentioned accelerometer.
>
> +config BMC150_ACCEL_SPI
> + tristate "SPI support"
> + depends on SPI
> + select IIO_BUFFER
> + select IIO_TRIGGERED_BUFFER
> + select REGMAP_SPI
> + help
> + Say yes here to build support for SPI communication with the
> + mentioned accelerometer.
If you move to the config approach I suggested earlier, these options
are hidden away avoiding the need for a help message ;)
> +
> endif
>
> config HID_SENSOR_ACCEL_3D
> diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile
> index 5ef8bdbad092..e579e93bf022 100644
> --- a/drivers/iio/accel/Makefile
> +++ b/drivers/iio/accel/Makefile
> @@ -6,6 +6,7 @@
> obj-$(CONFIG_BMA180) += bma180.o
> obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o
> obj-$(CONFIG_BMC150_ACCEL_I2C) += bmc150-accel-i2c.o
> +obj-$(CONFIG_BMC150_ACCEL_SPI) += bmc150-accel-spi.o
> obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o
> obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o
> obj-$(CONFIG_KXSD9) += kxsd9.o
> diff --git a/drivers/iio/accel/bmc150-accel-spi.c b/drivers/iio/accel/bmc150-accel-spi.c
> new file mode 100644
> index 000000000000..c13fd2aa5f34
> --- /dev/null
> +++ b/drivers/iio/accel/bmc150-accel-spi.c
> @@ -0,0 +1,86 @@
> +/*
> + * 3-axis accelerometer driver supporting following I2C Bosch-Sensortec chips:
Umm. Read the line above? Spot the obvious minor point ;)
> + * - BMC150
> + * - BMI055
> + * - BMA255
> + * - BMA250E
> + * - BMA222E
> + * - BMA280
> + *
> + * Copyright (c) 2014, Intel Corporation.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
> + * more details.
> + */
> +
> +#include <linux/device.h>
> +#include <linux/mod_devicetable.h>
> +#include <linux/module.h>
> +#include <linux/acpi.h>
> +#include <linux/regmap.h>
> +#include <linux/spi/spi.h>
> +
> +#include "bmc150-accel.h"
> +
> +static const struct regmap_config bmc150_spi_regmap_conf = {
> + .reg_bits = 8,
> + .val_bits = 8,
> + .max_register = 0x3f,
> +
> + .use_single_rw = false,
> + .cache_type = REGCACHE_NONE,
> +};
> +
> +static int bmc150_accel_probe(struct spi_device *spi)
> +{
> + struct regmap *regmap;
> + const struct spi_device_id *id = spi_get_device_id(spi);
> +
> + regmap = devm_regmap_init_spi(spi, &bmc150_spi_regmap_conf);
> + if (IS_ERR(regmap)) {
> + dev_err(&spi->dev, "Failed to initialize spi regmap\n");
> + return PTR_ERR(regmap);
> + }
> +
> + return bmc150_accel_core_probe(&spi->dev, regmap, spi->irq,
> + id->name, id->driver_data, true);
> +}
> +
> +static int bmc150_accel_remove(struct spi_device *spi)
> +{
> + return bmc150_accel_core_remove(&spi->dev);
> +}
> +
> +static const struct spi_device_id bmc150_accel_id[] = {
> + {"bmc150_accel", bmc150},
> + {"bmi055_accel", bmi055},
> + {"bma255", bma255},
> + {"bma250e", bma250e},
> + {"bma222e", bma222e},
> + {"bma280", bma280},
> + {}
> +};
> +
> +MODULE_DEVICE_TABLE(spi, bmc150_accel_id);
> +
> +static struct spi_driver bmc150_accel_driver = {
> + .driver = {
> + .name = "bmc150_accel_spi",
> + .acpi_match_table = ACPI_PTR(bmc150_accel_acpi_match),
> + .pm = &bmc150_accel_pm_ops,
> + },
> + .probe = bmc150_accel_probe,
> + .remove = bmc150_accel_remove,
> + .id_table = bmc150_accel_id,
> +};
> +module_spi_driver(bmc150_accel_driver);
> +
> +MODULE_AUTHOR("Markus Pargmann <[email protected]>");
> +MODULE_LICENSE("GPL v2");
> +MODULE_DESCRIPTION("BMC150 SPI accelerometer driver");
>
On Wed, Aug 12, 2015 at 10:12:22PM +0200, Hartmut Knaack wrote:
> Markus Pargmann schrieb am 12.08.2015 um 12:12:
> > There are some fields of this struct undocumented or old. This patch
> > updates the missing comments.
> >
> > Signed-off-by: Markus Pargmann <[email protected]>
> > ---
> > include/linux/regmap.h | 4 +++-
> > 1 file changed, 3 insertions(+), 1 deletion(-)
> >
> > diff --git a/include/linux/regmap.h b/include/linux/regmap.h
> > index 59c55ea0f0b5..6ff83c9ddb45 100644
> > --- a/include/linux/regmap.h
> > +++ b/include/linux/regmap.h
> > @@ -296,8 +296,11 @@ typedef void (*regmap_hw_free_context)(void *context);
> > * if not implemented on a given device.
> > * @async_write: Write operation which completes asynchronously, optional and
> > * must serialise with respect to non-async I/O.
> > + * @reg_write: Write operation for a register. Writes value to register.
> > * @read: Read operation. Data is returned in the buffer used to transmit
> > * data.
> > + * @reg_read: Read operation for a register. Reads a value from a register.
> > + * @free_conetext: Free context.
>
> Typo: free_context
Thanks, fixed for next version.
Best regards,
Markus
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
On Sat, Aug 15, 2015 at 02:13:14PM +0100, Jonathan Cameron wrote:
> On 12/08/15 11:12, Markus Pargmann wrote:
> > Valid irqs are > 0. This patch fixes the check which fails for the new
> > spi driver part if no interrupt was given.
> >
> > Signed-off-by: Markus Pargmann <[email protected]>
> This one crossed with Octavian's patch that cleaned up all cases of this.
> c176becd81843 iio: fix drivers that consider 0 as a valid IRQ in client->irq
>
> Hence you can drop this one from the v2 of this series.
Thanks, didn't notice this. Will drop it.
Best regards,
Markus
>
> (Its amazing how many times we get multiple patches for the same issue that
> has been there for ages in the same week or so!)
>
> Jonathan
> > ---
> > drivers/iio/accel/bmc150-accel.c | 4 ++--
> > 1 file changed, 2 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel.c
> > index 4e70f51c2370..fe2d2316158f 100644
> > --- a/drivers/iio/accel/bmc150-accel.c
> > +++ b/drivers/iio/accel/bmc150-accel.c
> > @@ -1660,10 +1660,10 @@ static int bmc150_accel_probe(struct i2c_client *client,
> > return ret;
> > }
> >
> > - if (client->irq < 0)
> > + if (client->irq <= 0)
> > client->irq = bmc150_accel_gpio_probe(client, data);
> >
> > - if (client->irq >= 0) {
> > + if (client->irq > 0) {
> > ret = devm_request_threaded_irq(
> > &client->dev, client->irq,
> > bmc150_accel_irq_handler,
> >
>
>
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
On Sat, Aug 15, 2015 at 02:27:47PM +0100, Jonathan Cameron wrote:
> On 12/08/15 11:12, Markus Pargmann wrote:
> > This replaces all usage of direct i2c accesses with regmap accesses.
> >
> > Signed-off-by: Markus Pargmann <[email protected]>
> Clearly there is some work needed on the earlier patches and this
> might change as a result (particularly the fifo read). I'll review
> as is however..
>
> Few bits on top of what other reviews have highlighted...
>
> Jonathan
> > ---
> > drivers/iio/accel/Kconfig | 2 +
> > drivers/iio/accel/bmc150-accel.c | 225 +++++++++++++++++----------------------
> > 2 files changed, 101 insertions(+), 126 deletions(-)
> >
> > diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
> > index 00e7bcbdbe24..01dd03d194d1 100644
> > --- a/drivers/iio/accel/Kconfig
> > +++ b/drivers/iio/accel/Kconfig
> > @@ -22,6 +22,8 @@ config BMC150_ACCEL
> > depends on I2C
> > select IIO_BUFFER
> > select IIO_TRIGGERED_BUFFER
> > + select REGMAP
> > + select REGMAP_I2C
> > help
> > Say yes here to build support for the following Bosch accelerometers:
> > BMC150, BMI055, BMA250E, BMA222E, BMA255, BMA280.
> > diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel.c
> > index fe2d2316158f..1484e956482e 100644
> > --- a/drivers/iio/accel/bmc150-accel.c
> > +++ b/drivers/iio/accel/bmc150-accel.c
> > @@ -35,6 +35,7 @@
> > #include <linux/iio/trigger.h>
> > #include <linux/iio/trigger_consumer.h>
> > #include <linux/iio/triggered_buffer.h>
> > +#include <linux/regmap.h>
> >
> > #define BMC150_ACCEL_DRV_NAME "bmc150_accel"
> > #define BMC150_ACCEL_IRQ_NAME "bmc150_accel_event"
> > @@ -185,6 +186,8 @@ enum bmc150_accel_trigger_id {
> >
> > struct bmc150_accel_data {
> > struct i2c_client *client;
> > + struct regmap *regmap;
> > + struct device *dev;
> > struct bmc150_accel_interrupt interrupts[BMC150_ACCEL_INTERRUPTS];
> > atomic_t active_intr;
> > struct bmc150_accel_trigger triggers[BMC150_ACCEL_TRIGGERS];
> > @@ -241,6 +244,14 @@ static const struct {
> > {500000, BMC150_ACCEL_SLEEP_500_MS},
> > {1000000, BMC150_ACCEL_SLEEP_1_SEC} };
> >
> > +static const struct regmap_config bmc150_i2c_regmap_conf = {
> > + .reg_bits = 8,
> > + .val_bits = 8,
> > + .max_register = 0x3f,
> > +
> > + .use_single_rw = false,
> > + .cache_type = REGCACHE_NONE,
> > +};
> >
> > static int bmc150_accel_set_mode(struct bmc150_accel_data *data,
> > enum bmc150_power_modes mode,
> > @@ -270,8 +281,7 @@ static int bmc150_accel_set_mode(struct bmc150_accel_data *data,
> >
> > dev_dbg(&data->client->dev, "Set Mode bits %x\n", lpw_bits);
> >
> > - ret = i2c_smbus_write_byte_data(data->client,
> > - BMC150_ACCEL_REG_PMU_LPW, lpw_bits);
> > + ret = regmap_write(data->regmap, BMC150_ACCEL_REG_PMU_LPW, lpw_bits);
> > if (ret < 0) {
> > dev_err(&data->client->dev, "Error writing reg_pmu_lpw\n");
> > return ret;
> > @@ -289,8 +299,7 @@ static int bmc150_accel_set_bw(struct bmc150_accel_data *data, int val,
> > for (i = 0; i < ARRAY_SIZE(bmc150_accel_samp_freq_table); ++i) {
> > if (bmc150_accel_samp_freq_table[i].val == val &&
> > bmc150_accel_samp_freq_table[i].val2 == val2) {
> > - ret = i2c_smbus_write_byte_data(
> > - data->client,
> > + ret = regmap_write(data->regmap,
> > BMC150_ACCEL_REG_PMU_BW,
> > bmc150_accel_samp_freq_table[i].bw_bits);
> > if (ret < 0)
> > @@ -307,26 +316,19 @@ static int bmc150_accel_set_bw(struct bmc150_accel_data *data, int val,
> >
> > static int bmc150_accel_update_slope(struct bmc150_accel_data *data)
> > {
> > - int ret, val;
> > + int ret;
> >
> > - ret = i2c_smbus_write_byte_data(data->client, BMC150_ACCEL_REG_INT_6,
> > + ret = regmap_write(data->regmap, BMC150_ACCEL_REG_INT_6,
> > data->slope_thres);
> > if (ret < 0) {
> > dev_err(&data->client->dev, "Error writing reg_int_6\n");
> > return ret;
> > }
> >
> > - ret = i2c_smbus_read_byte_data(data->client, BMC150_ACCEL_REG_INT_5);
> > + ret = regmap_update_bits(data->regmap, BMC150_ACCEL_REG_INT_5,
> > + BMC150_ACCEL_SLOPE_DUR_MASK, data->slope_dur);
> > if (ret < 0) {
> > - dev_err(&data->client->dev, "Error reading reg_int_5\n");
> > - return ret;
> > - }
> > -
> > - val = (ret & ~BMC150_ACCEL_SLOPE_DUR_MASK) | data->slope_dur;
> > - ret = i2c_smbus_write_byte_data(data->client, BMC150_ACCEL_REG_INT_5,
> > - val);
> > - if (ret < 0) {
> > - dev_err(&data->client->dev, "Error write reg_int_5\n");
> > + dev_err(&data->client->dev, "Error updating reg_int_5\n");
> > return ret;
> > }
> >
> > @@ -348,17 +350,18 @@ static int bmc150_accel_any_motion_setup(struct bmc150_accel_trigger *t,
> > static int bmc150_accel_chip_init(struct bmc150_accel_data *data)
> > {
> > int ret;
> > + unsigned int val;
> >
> > - ret = i2c_smbus_read_byte_data(data->client, BMC150_ACCEL_REG_CHIP_ID);
> > + ret = regmap_read(data->regmap, BMC150_ACCEL_REG_CHIP_ID, &val);
> > if (ret < 0) {
> > dev_err(&data->client->dev,
> > "Error: Reading chip id\n");
> > return ret;
> > }
> >
> > - dev_dbg(&data->client->dev, "Chip Id %x\n", ret);
> > - if (ret != data->chip_info->chip_id) {
> > - dev_err(&data->client->dev, "Invalid chip %x\n", ret);
> > + dev_dbg(&data->client->dev, "Chip Id %x\n", val);
> > + if (val != data->chip_info->chip_id) {
> > + dev_err(&data->client->dev, "Invalid chip %x\n", val);
> > return -ENODEV;
> > }
> >
> > @@ -372,9 +375,8 @@ static int bmc150_accel_chip_init(struct bmc150_accel_data *data)
> > return ret;
> >
> > /* Set Default Range */
> > - ret = i2c_smbus_write_byte_data(data->client,
> > - BMC150_ACCEL_REG_PMU_RANGE,
> > - BMC150_ACCEL_DEF_RANGE_4G);
> > + ret = regmap_write(data->regmap, BMC150_ACCEL_REG_PMU_RANGE,
> > + BMC150_ACCEL_DEF_RANGE_4G);
> > if (ret < 0) {
> > dev_err(&data->client->dev,
> > "Error writing reg_pmu_range\n");
> > @@ -391,10 +393,9 @@ static int bmc150_accel_chip_init(struct bmc150_accel_data *data)
> > return ret;
> >
> > /* Set default as latched interrupts */
> > - ret = i2c_smbus_write_byte_data(data->client,
> > - BMC150_ACCEL_REG_INT_RST_LATCH,
> > - BMC150_ACCEL_INT_MODE_LATCH_INT |
> > - BMC150_ACCEL_INT_MODE_LATCH_RESET);
> > + ret = regmap_write(data->regmap, BMC150_ACCEL_REG_INT_RST_LATCH,
> > + BMC150_ACCEL_INT_MODE_LATCH_INT |
> > + BMC150_ACCEL_INT_MODE_LATCH_RESET);
> > if (ret < 0) {
> > dev_err(&data->client->dev,
> > "Error writing reg_int_rst_latch\n");
> > @@ -527,38 +528,18 @@ static int bmc150_accel_set_interrupt(struct bmc150_accel_data *data, int i,
> > return ret;
> >
> > /* map the interrupt to the appropriate pins */
> > - ret = i2c_smbus_read_byte_data(data->client, info->map_reg);
> > - if (ret < 0) {
> > - dev_err(&data->client->dev, "Error reading reg_int_map\n");
> > - goto out_fix_power_state;
> > - }
> > - if (state)
> > - ret |= info->map_bitmask;
> > - else
> > - ret &= ~info->map_bitmask;
> > -
> > - ret = i2c_smbus_write_byte_data(data->client, info->map_reg,
> > - ret);
> > + ret = regmap_update_bits(data->regmap, info->map_reg, info->map_bitmask,
> > + (state ? info->map_bitmask : 0));
> > if (ret < 0) {
> > - dev_err(&data->client->dev, "Error writing reg_int_map\n");
> > + dev_err(&data->client->dev, "Error updating reg_int_map\n");
> > goto out_fix_power_state;
> > }
> >
> > /* enable/disable the interrupt */
> > - ret = i2c_smbus_read_byte_data(data->client, info->en_reg);
> > - if (ret < 0) {
> > - dev_err(&data->client->dev, "Error reading reg_int_en\n");
> > - goto out_fix_power_state;
> > - }
> > -
> > - if (state)
> > - ret |= info->en_bitmask;
> > - else
> > - ret &= ~info->en_bitmask;
> > -
> > - ret = i2c_smbus_write_byte_data(data->client, info->en_reg, ret);
> > + ret = regmap_update_bits(data->regmap, info->en_reg, info->en_bitmask,
> > + (state ? info->en_bitmask : 0));
> > if (ret < 0) {
> > - dev_err(&data->client->dev, "Error writing reg_int_en\n");
> > + dev_err(&data->client->dev, "Error updating reg_int_en\n");
> > goto out_fix_power_state;
> > }
> >
> > @@ -581,8 +562,7 @@ static int bmc150_accel_set_scale(struct bmc150_accel_data *data, int val)
> >
> > for (i = 0; i < ARRAY_SIZE(data->chip_info->scale_table); ++i) {
> > if (data->chip_info->scale_table[i].scale == val) {
> > - ret = i2c_smbus_write_byte_data(
> > - data->client,
> > + ret = regmap_write(data->regmap,
> > BMC150_ACCEL_REG_PMU_RANGE,
> > data->chip_info->scale_table[i].reg_range);
> > if (ret < 0) {
> > @@ -602,16 +582,17 @@ static int bmc150_accel_set_scale(struct bmc150_accel_data *data, int val)
> > static int bmc150_accel_get_temp(struct bmc150_accel_data *data, int *val)
> > {
> > int ret;
> > + unsigned int value;
> >
> > mutex_lock(&data->mutex);
> >
> > - ret = i2c_smbus_read_byte_data(data->client, BMC150_ACCEL_REG_TEMP);
> > + ret = regmap_read(data->regmap, BMC150_ACCEL_REG_TEMP, &value);
> > if (ret < 0) {
> > dev_err(&data->client->dev, "Error reading reg_temp\n");
> > mutex_unlock(&data->mutex);
> > return ret;
> > }
> > - *val = sign_extend32(ret, 7);
> > + *val = sign_extend32(value, 7);
> >
> > mutex_unlock(&data->mutex);
> >
> > @@ -624,6 +605,7 @@ static int bmc150_accel_get_axis(struct bmc150_accel_data *data,
> > {
> > int ret;
> > int axis = chan->scan_index;
> > + unsigned int raw_val;
> >
> > mutex_lock(&data->mutex);
> > ret = bmc150_accel_set_power_state(data, true);
> > @@ -632,15 +614,15 @@ static int bmc150_accel_get_axis(struct bmc150_accel_data *data,
> > return ret;
> > }
> >
> > - ret = i2c_smbus_read_word_data(data->client,
> > - BMC150_ACCEL_AXIS_TO_REG(axis));
> > + ret = regmap_bulk_read(data->regmap, BMC150_ACCEL_AXIS_TO_REG(axis),
> > + &raw_val, 2);
> > if (ret < 0) {
> > dev_err(&data->client->dev, "Error reading axis %d\n", axis);
> > bmc150_accel_set_power_state(data, false);
> > mutex_unlock(&data->mutex);
> > return ret;
> > }
> > - *val = sign_extend32(ret >> chan->scan_type.shift,
> > + *val = sign_extend32(raw_val >> chan->scan_type.shift,
> > chan->scan_type.realbits - 1);
> > ret = bmc150_accel_set_power_state(data, false);
> > mutex_unlock(&data->mutex);
> > @@ -904,52 +886,37 @@ static int bmc150_accel_set_watermark(struct iio_dev *indio_dev, unsigned val)
> > * We must read at least one full frame in one burst, otherwise the rest of the
> > * frame data is discarded.
> > */
> > -static int bmc150_accel_fifo_transfer(const struct i2c_client *client,
> > +static int bmc150_accel_fifo_transfer(struct bmc150_accel_data *data,
> > char *buffer, int samples)
> > {
> > int sample_length = 3 * 2;
> > - u8 reg_fifo_data = BMC150_ACCEL_REG_FIFO_DATA;
> > - int ret = -EIO;
> > -
> > - if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
> > - struct i2c_msg msg[2] = {
> > - {
> > - .addr = client->addr,
> > - .flags = 0,
> > - .buf = ®_fifo_data,
> > - .len = sizeof(reg_fifo_data),
> > - },
> > - {
> > - .addr = client->addr,
> > - .flags = I2C_M_RD,
> > - .buf = (u8 *)buffer,
> > - .len = samples * sample_length,
> > - }
> > - };
> > + int ret;
> > + int total_length = samples * sample_length;
> > + int i, step;
> >
> > - ret = i2c_transfer(client->adapter, msg, 2);
> > - if (ret != 2)
> > - ret = -EIO;
> > - else
> > - ret = 0;
> > - } else {
> > - int i, step = I2C_SMBUS_BLOCK_MAX / sample_length;
> > -
> > - for (i = 0; i < samples * sample_length; i += step) {
> > - ret = i2c_smbus_read_i2c_block_data(client,
> > - reg_fifo_data, step,
> > - &buffer[i]);
> > - if (ret != step) {
> > - ret = -EIO;
> > - break;
> > - }
> > + ret = regmap_raw_read(data->regmap, BMC150_ACCEL_REG_FIFO_DATA, buffer,
> > + total_length);
> > + if (ret != -E2BIG) {
> > + if (ret)
> I'd invert the logic for more readability.
>
> if (ret == -E2BIT) {
> ...
> } else if (ret) {
> ...
> } else {
> return ret;
> }
Okay.
> > + dev_err(data->dev, "Error transferring data from fifo\n");
> > + return ret;
> > + }
> >
> > - ret = 0;
> > - }
> > + /*
> > + * Seems we have a bus with size limitation so we have to execute
> > + * multiple reads
> > + */
> Can we not just query this in advance before going through the previous
> failed call? THat would be cleaner to my mind.
Yes we can check that in advance and make the reads accordingly.
>
> > + step = regmap_get_raw_io_max(data->regmap) / sample_length;
> > + for (i = -1; i < samples * sample_length; i += step) {
> > + ret = regmap_raw_read(data->regmap, BMC150_ACCEL_REG_FIFO_DATA,
> > + &buffer[i], step);
> umm. Can't say I like the negative index into buffer. Why is it
> necessary?
No this is an error, thanks.
> > + if (ret)
> > + break;
> > }
> >
> > if (ret)
> > - dev_err(&client->dev, "Error transferring data from fifo\n");
> > + dev_err(data->dev, "Error transferring data from fifo in single steps of %zu\n",
>
> multiple steps of %zu perhaps?
Yes.
> > + step);
> >
> > return ret;
> > }
> > @@ -963,14 +930,15 @@ static int __bmc150_accel_fifo_flush(struct iio_dev *indio_dev,
> > u16 buffer[BMC150_ACCEL_FIFO_LENGTH * 3];
> > int64_t tstamp;
> > uint64_t sample_period;
> > - ret = i2c_smbus_read_byte_data(data->client,
> > - BMC150_ACCEL_REG_FIFO_STATUS);
> > + unsigned int val;
> > +
> > + ret = regmap_read(data->regmap, BMC150_ACCEL_REG_FIFO_STATUS, &val);
> > if (ret < 0) {
> > dev_err(&data->client->dev, "Error reading reg_fifo_status\n");
> > return ret;
> > }
> >
> > - count = ret & 0x7F;
> > + count = val & 0x7F;
> >
> > if (!count)
> > return 0;
> > @@ -1009,7 +977,7 @@ static int __bmc150_accel_fifo_flush(struct iio_dev *indio_dev,
> > if (samples && count > samples)
> > count = samples;
> >
> > - ret = bmc150_accel_fifo_transfer(data->client, (u8 *)buffer, count);
> > + ret = bmc150_accel_fifo_transfer(data, (u8 *)buffer, count);
> > if (ret)
> > return ret;
> >
> > @@ -1206,17 +1174,19 @@ static irqreturn_t bmc150_accel_trigger_handler(int irq, void *p)
> > struct iio_dev *indio_dev = pf->indio_dev;
> > struct bmc150_accel_data *data = iio_priv(indio_dev);
> > int bit, ret, i = 0;
> > + unsigned int raw_val;
> >
> > mutex_lock(&data->mutex);
> > for_each_set_bit(bit, indio_dev->active_scan_mask,
> > indio_dev->masklength) {
> > - ret = i2c_smbus_read_word_data(data->client,
> > - BMC150_ACCEL_AXIS_TO_REG(bit));
> > + ret = regmap_bulk_read(data->regmap,
> > + BMC150_ACCEL_AXIS_TO_REG(bit), &raw_val,
> > + 2);
> Is using a variable on the stack not going to cause issues when we add
> SPI? (cacheline dma requirements).
Good question. Just looked it up. regmap uses spi_write_then_read which
uses its own buffer and copies the result back to the receive buffer at
the end. So this shouldn't be a problem.
Thanks,
Markus
> > if (ret < 0) {
> > mutex_unlock(&data->mutex);
> > goto err_read;
> > }
> > - data->buffer[i++] = ret;
> > + data->buffer[i++] = raw_val;
> > }
> > mutex_unlock(&data->mutex);
> >
> > @@ -1240,10 +1210,9 @@ static int bmc150_accel_trig_try_reen(struct iio_trigger *trig)
> >
> > mutex_lock(&data->mutex);
> > /* clear any latched interrupt */
> > - ret = i2c_smbus_write_byte_data(data->client,
> > - BMC150_ACCEL_REG_INT_RST_LATCH,
> > - BMC150_ACCEL_INT_MODE_LATCH_INT |
> > - BMC150_ACCEL_INT_MODE_LATCH_RESET);
> > + ret = regmap_write(data->regmap, BMC150_ACCEL_REG_INT_RST_LATCH,
> > + BMC150_ACCEL_INT_MODE_LATCH_INT |
> > + BMC150_ACCEL_INT_MODE_LATCH_RESET);
> > mutex_unlock(&data->mutex);
> > if (ret < 0) {
> > dev_err(&data->client->dev,
> > @@ -1300,34 +1269,34 @@ static int bmc150_accel_handle_roc_event(struct iio_dev *indio_dev)
> > struct bmc150_accel_data *data = iio_priv(indio_dev);
> > int dir;
> > int ret;
> > + unsigned int val;
> >
> > - ret = i2c_smbus_read_byte_data(data->client,
> > - BMC150_ACCEL_REG_INT_STATUS_2);
> > + ret = regmap_read(data->regmap, BMC150_ACCEL_REG_INT_STATUS_2, &val);
> > if (ret < 0) {
> > dev_err(&data->client->dev, "Error reading reg_int_status_2\n");
> > return ret;
> > }
> >
> > - if (ret & BMC150_ACCEL_ANY_MOTION_BIT_SIGN)
> > + if (val & BMC150_ACCEL_ANY_MOTION_BIT_SIGN)
> > dir = IIO_EV_DIR_FALLING;
> > else
> > dir = IIO_EV_DIR_RISING;
> >
> > - if (ret & BMC150_ACCEL_ANY_MOTION_BIT_X)
> > + if (val & BMC150_ACCEL_ANY_MOTION_BIT_X)
> > iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL,
> > 0,
> > IIO_MOD_X,
> > IIO_EV_TYPE_ROC,
> > dir),
> > data->timestamp);
> > - if (ret & BMC150_ACCEL_ANY_MOTION_BIT_Y)
> > + if (val & BMC150_ACCEL_ANY_MOTION_BIT_Y)
> > iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL,
> > 0,
> > IIO_MOD_Y,
> > IIO_EV_TYPE_ROC,
> > dir),
> > data->timestamp);
> > - if (ret & BMC150_ACCEL_ANY_MOTION_BIT_Z)
> > + if (val & BMC150_ACCEL_ANY_MOTION_BIT_Z)
> > iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL,
> > 0,
> > IIO_MOD_Z,
> > @@ -1360,10 +1329,9 @@ static irqreturn_t bmc150_accel_irq_thread_handler(int irq, void *private)
> > }
> >
> > if (ack) {
> > - ret = i2c_smbus_write_byte_data(data->client,
> > - BMC150_ACCEL_REG_INT_RST_LATCH,
> > - BMC150_ACCEL_INT_MODE_LATCH_INT |
> > - BMC150_ACCEL_INT_MODE_LATCH_RESET);
> > + ret = regmap_write(data->regmap, BMC150_ACCEL_REG_INT_RST_LATCH,
> > + BMC150_ACCEL_INT_MODE_LATCH_INT |
> > + BMC150_ACCEL_INT_MODE_LATCH_RESET);
> > if (ret)
> > dev_err(&data->client->dev, "Error writing reg_int_rst_latch\n");
> > ret = IRQ_HANDLED;
> > @@ -1516,7 +1484,7 @@ static int bmc150_accel_fifo_set_mode(struct bmc150_accel_data *data)
> > u8 reg = BMC150_ACCEL_REG_FIFO_CONFIG1;
> > int ret;
> >
> > - ret = i2c_smbus_write_byte_data(data->client, reg, data->fifo_mode);
> > + ret = regmap_write(data->regmap, reg, data->fifo_mode);
> > if (ret < 0) {
> > dev_err(&data->client->dev, "Error writing reg_fifo_config1\n");
> > return ret;
> > @@ -1525,9 +1493,8 @@ static int bmc150_accel_fifo_set_mode(struct bmc150_accel_data *data)
> > if (!data->fifo_mode)
> > return 0;
> >
> > - ret = i2c_smbus_write_byte_data(data->client,
> > - BMC150_ACCEL_REG_FIFO_CONFIG0,
> > - data->watermark);
> > + ret = regmap_write(data->regmap, BMC150_ACCEL_REG_FIFO_CONFIG0,
> > + data->watermark);
> > if (ret < 0)
> > dev_err(&data->client->dev, "Error writing reg_fifo_config0\n");
> >
> > @@ -1627,6 +1594,13 @@ static int bmc150_accel_probe(struct i2c_client *client,
> > data = iio_priv(indio_dev);
> > i2c_set_clientdata(client, indio_dev);
> > data->client = client;
> > + data->dev = &client->dev;
> > +
> > + data->regmap = devm_regmap_init_i2c(client, &bmc150_i2c_regmap_conf);
> > + if (IS_ERR(data->regmap)) {
> > + dev_err(&client->dev, "Failed to initialize i2c regmap\n");
> > + return PTR_ERR(data->regmap);
> > + }
> >
> > if (id) {
> > name = id->name;
> > @@ -1680,9 +1654,8 @@ static int bmc150_accel_probe(struct i2c_client *client,
> > * want to use latch mode when we can to prevent interrupt
> > * flooding.
> > */
> > - ret = i2c_smbus_write_byte_data(data->client,
> > - BMC150_ACCEL_REG_INT_RST_LATCH,
> > - BMC150_ACCEL_INT_MODE_LATCH_RESET);
> > + ret = regmap_write(data->regmap, BMC150_ACCEL_REG_INT_RST_LATCH,
> > + BMC150_ACCEL_INT_MODE_LATCH_RESET);
> > if (ret < 0) {
> > dev_err(&data->client->dev, "Error writing reg_int_rst_latch\n");
> > goto err_buffer_cleanup;
> >
>
>
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
On Sat, Aug 15, 2015 at 02:33:51PM +0100, Jonathan Cameron wrote:
> On 12/08/15 11:12, Markus Pargmann wrote:
> > i2c_client struct is now only used for debugging output. We can use the
> > device struct as well so we can remove all struct i2c_client usage.
> >
> > Signed-off-by: Markus Pargmann <[email protected]>
> This one looks fine to me.
>
> Acked-by: Jonathan Cameron <[email protected]>
>
> Ideally these bmc150 patches should also get a look from Srinivas
> before merging however (and testing given I'm guessing you don't have
> all the parts!)
Thanks. Yes indeed, I only have the SPI parts. Also to keep the fifo
read support of the bmc150 as it is in the driver currently the regmap
series has to be fixed.
Best Regards,
Markus
>
> Jonathan
> > ---
> > drivers/iio/accel/bmc150-accel.c | 120 +++++++++++++++++++--------------------
> > 1 file changed, 58 insertions(+), 62 deletions(-)
> >
> > diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel.c
> > index 1484e956482e..d75e1b0aa7e9 100644
> > --- a/drivers/iio/accel/bmc150-accel.c
> > +++ b/drivers/iio/accel/bmc150-accel.c
> > @@ -185,9 +185,9 @@ enum bmc150_accel_trigger_id {
> > };
> >
> > struct bmc150_accel_data {
> > - struct i2c_client *client;
> > struct regmap *regmap;
> > struct device *dev;
> > + int irq;
> > struct bmc150_accel_interrupt interrupts[BMC150_ACCEL_INTERRUPTS];
> > atomic_t active_intr;
> > struct bmc150_accel_trigger triggers[BMC150_ACCEL_TRIGGERS];
> > @@ -279,11 +279,11 @@ static int bmc150_accel_set_mode(struct bmc150_accel_data *data,
> > lpw_bits = mode << BMC150_ACCEL_PMU_MODE_SHIFT;
> > lpw_bits |= (dur_val << BMC150_ACCEL_PMU_BIT_SLEEP_DUR_SHIFT);
> >
> > - dev_dbg(&data->client->dev, "Set Mode bits %x\n", lpw_bits);
> > + dev_dbg(data->dev, "Set Mode bits %x\n", lpw_bits);
> >
> > ret = regmap_write(data->regmap, BMC150_ACCEL_REG_PMU_LPW, lpw_bits);
> > if (ret < 0) {
> > - dev_err(&data->client->dev, "Error writing reg_pmu_lpw\n");
> > + dev_err(data->dev, "Error writing reg_pmu_lpw\n");
> > return ret;
> > }
> >
> > @@ -321,18 +321,18 @@ static int bmc150_accel_update_slope(struct bmc150_accel_data *data)
> > ret = regmap_write(data->regmap, BMC150_ACCEL_REG_INT_6,
> > data->slope_thres);
> > if (ret < 0) {
> > - dev_err(&data->client->dev, "Error writing reg_int_6\n");
> > + dev_err(data->dev, "Error writing reg_int_6\n");
> > return ret;
> > }
> >
> > ret = regmap_update_bits(data->regmap, BMC150_ACCEL_REG_INT_5,
> > BMC150_ACCEL_SLOPE_DUR_MASK, data->slope_dur);
> > if (ret < 0) {
> > - dev_err(&data->client->dev, "Error updating reg_int_5\n");
> > + dev_err(data->dev, "Error updating reg_int_5\n");
> > return ret;
> > }
> >
> > - dev_dbg(&data->client->dev, "%s: %x %x\n", __func__, data->slope_thres,
> > + dev_dbg(data->dev, "%s: %x %x\n", __func__, data->slope_thres,
> > data->slope_dur);
> >
> > return ret;
> > @@ -354,14 +354,14 @@ static int bmc150_accel_chip_init(struct bmc150_accel_data *data)
> >
> > ret = regmap_read(data->regmap, BMC150_ACCEL_REG_CHIP_ID, &val);
> > if (ret < 0) {
> > - dev_err(&data->client->dev,
> > + dev_err(data->dev,
> > "Error: Reading chip id\n");
> > return ret;
> > }
> >
> > - dev_dbg(&data->client->dev, "Chip Id %x\n", val);
> > + dev_dbg(data->dev, "Chip Id %x\n", val);
> > if (val != data->chip_info->chip_id) {
> > - dev_err(&data->client->dev, "Invalid chip %x\n", val);
> > + dev_err(data->dev, "Invalid chip %x\n", val);
> > return -ENODEV;
> > }
> >
> > @@ -378,8 +378,7 @@ static int bmc150_accel_chip_init(struct bmc150_accel_data *data)
> > ret = regmap_write(data->regmap, BMC150_ACCEL_REG_PMU_RANGE,
> > BMC150_ACCEL_DEF_RANGE_4G);
> > if (ret < 0) {
> > - dev_err(&data->client->dev,
> > - "Error writing reg_pmu_range\n");
> > + dev_err(data->dev, "Error writing reg_pmu_range\n");
> > return ret;
> > }
> >
> > @@ -397,7 +396,7 @@ static int bmc150_accel_chip_init(struct bmc150_accel_data *data)
> > BMC150_ACCEL_INT_MODE_LATCH_INT |
> > BMC150_ACCEL_INT_MODE_LATCH_RESET);
> > if (ret < 0) {
> > - dev_err(&data->client->dev,
> > + dev_err(data->dev,
> > "Error writing reg_int_rst_latch\n");
> > return ret;
> > }
> > @@ -439,16 +438,16 @@ static int bmc150_accel_set_power_state(struct bmc150_accel_data *data, bool on)
> > int ret;
> >
> > if (on)
> > - ret = pm_runtime_get_sync(&data->client->dev);
> > + ret = pm_runtime_get_sync(data->dev);
> > else {
> > - pm_runtime_mark_last_busy(&data->client->dev);
> > - ret = pm_runtime_put_autosuspend(&data->client->dev);
> > + pm_runtime_mark_last_busy(data->dev);
> > + ret = pm_runtime_put_autosuspend(data->dev);
> > }
> > if (ret < 0) {
> > - dev_err(&data->client->dev,
> > + dev_err(data->dev,
> > "Failed: bmc150_accel_set_power_state for %d\n", on);
> > if (on)
> > - pm_runtime_put_noidle(&data->client->dev);
> > + pm_runtime_put_noidle(data->dev);
> >
> > return ret;
> > }
> > @@ -531,7 +530,7 @@ static int bmc150_accel_set_interrupt(struct bmc150_accel_data *data, int i,
> > ret = regmap_update_bits(data->regmap, info->map_reg, info->map_bitmask,
> > (state ? info->map_bitmask : 0));
> > if (ret < 0) {
> > - dev_err(&data->client->dev, "Error updating reg_int_map\n");
> > + dev_err(data->dev, "Error updating reg_int_map\n");
> > goto out_fix_power_state;
> > }
> >
> > @@ -539,7 +538,7 @@ static int bmc150_accel_set_interrupt(struct bmc150_accel_data *data, int i,
> > ret = regmap_update_bits(data->regmap, info->en_reg, info->en_bitmask,
> > (state ? info->en_bitmask : 0));
> > if (ret < 0) {
> > - dev_err(&data->client->dev, "Error updating reg_int_en\n");
> > + dev_err(data->dev, "Error updating reg_int_en\n");
> > goto out_fix_power_state;
> > }
> >
> > @@ -566,7 +565,7 @@ static int bmc150_accel_set_scale(struct bmc150_accel_data *data, int val)
> > BMC150_ACCEL_REG_PMU_RANGE,
> > data->chip_info->scale_table[i].reg_range);
> > if (ret < 0) {
> > - dev_err(&data->client->dev,
> > + dev_err(data->dev,
> > "Error writing pmu_range\n");
> > return ret;
> > }
> > @@ -588,7 +587,7 @@ static int bmc150_accel_get_temp(struct bmc150_accel_data *data, int *val)
> >
> > ret = regmap_read(data->regmap, BMC150_ACCEL_REG_TEMP, &value);
> > if (ret < 0) {
> > - dev_err(&data->client->dev, "Error reading reg_temp\n");
> > + dev_err(data->dev, "Error reading reg_temp\n");
> > mutex_unlock(&data->mutex);
> > return ret;
> > }
> > @@ -617,7 +616,7 @@ static int bmc150_accel_get_axis(struct bmc150_accel_data *data,
> > ret = regmap_bulk_read(data->regmap, BMC150_ACCEL_AXIS_TO_REG(axis),
> > &raw_val, 2);
> > if (ret < 0) {
> > - dev_err(&data->client->dev, "Error reading axis %d\n", axis);
> > + dev_err(data->dev, "Error reading axis %d\n", axis);
> > bmc150_accel_set_power_state(data, false);
> > mutex_unlock(&data->mutex);
> > return ret;
> > @@ -934,7 +933,7 @@ static int __bmc150_accel_fifo_flush(struct iio_dev *indio_dev,
> >
> > ret = regmap_read(data->regmap, BMC150_ACCEL_REG_FIFO_STATUS, &val);
> > if (ret < 0) {
> > - dev_err(&data->client->dev, "Error reading reg_fifo_status\n");
> > + dev_err(data->dev, "Error reading reg_fifo_status\n");
> > return ret;
> > }
> >
> > @@ -1215,7 +1214,7 @@ static int bmc150_accel_trig_try_reen(struct iio_trigger *trig)
> > BMC150_ACCEL_INT_MODE_LATCH_RESET);
> > mutex_unlock(&data->mutex);
> > if (ret < 0) {
> > - dev_err(&data->client->dev,
> > + dev_err(data->dev,
> > "Error writing reg_int_rst_latch\n");
> > return ret;
> > }
> > @@ -1273,7 +1272,7 @@ static int bmc150_accel_handle_roc_event(struct iio_dev *indio_dev)
> >
> > ret = regmap_read(data->regmap, BMC150_ACCEL_REG_INT_STATUS_2, &val);
> > if (ret < 0) {
> > - dev_err(&data->client->dev, "Error reading reg_int_status_2\n");
> > + dev_err(data->dev, "Error reading reg_int_status_2\n");
> > return ret;
> > }
> >
> > @@ -1333,7 +1332,7 @@ static irqreturn_t bmc150_accel_irq_thread_handler(int irq, void *private)
> > BMC150_ACCEL_INT_MODE_LATCH_INT |
> > BMC150_ACCEL_INT_MODE_LATCH_RESET);
> > if (ret)
> > - dev_err(&data->client->dev, "Error writing reg_int_rst_latch\n");
> > + dev_err(data->dev, "Error writing reg_int_rst_latch\n");
> > ret = IRQ_HANDLED;
> > } else {
> > ret = IRQ_NONE;
> > @@ -1385,17 +1384,13 @@ static const char *bmc150_accel_match_acpi_device(struct device *dev, int *data)
> > return dev_name(dev);
> > }
> >
> > -static int bmc150_accel_gpio_probe(struct i2c_client *client,
> > - struct bmc150_accel_data *data)
> > +static int bmc150_accel_gpio_probe(struct bmc150_accel_data *data)
> > {
> > struct device *dev;
> > struct gpio_desc *gpio;
> > int ret;
> >
> > - if (!client)
> > - return -EINVAL;
> > -
> > - dev = &client->dev;
> > + dev = data->dev;
> >
> > /* data ready gpio interrupt pin */
> > gpio = devm_gpiod_get_index(dev, BMC150_ACCEL_GPIO_NAME, 0, GPIOD_IN);
> > @@ -1448,7 +1443,7 @@ static int bmc150_accel_triggers_setup(struct iio_dev *indio_dev,
> > for (i = 0; i < BMC150_ACCEL_TRIGGERS; i++) {
> > struct bmc150_accel_trigger *t = &data->triggers[i];
> >
> > - t->indio_trig = devm_iio_trigger_alloc(&data->client->dev,
> > + t->indio_trig = devm_iio_trigger_alloc(data->dev,
> > bmc150_accel_triggers[i].name,
> > indio_dev->name,
> > indio_dev->id);
> > @@ -1457,7 +1452,7 @@ static int bmc150_accel_triggers_setup(struct iio_dev *indio_dev,
> > break;
> > }
> >
> > - t->indio_trig->dev.parent = &data->client->dev;
> > + t->indio_trig->dev.parent = data->dev;
> > t->indio_trig->ops = &bmc150_accel_trigger_ops;
> > t->intr = bmc150_accel_triggers[i].intr;
> > t->data = data;
> > @@ -1486,7 +1481,7 @@ static int bmc150_accel_fifo_set_mode(struct bmc150_accel_data *data)
> >
> > ret = regmap_write(data->regmap, reg, data->fifo_mode);
> > if (ret < 0) {
> > - dev_err(&data->client->dev, "Error writing reg_fifo_config1\n");
> > + dev_err(data->dev, "Error writing reg_fifo_config1\n");
> > return ret;
> > }
> >
> > @@ -1496,7 +1491,7 @@ static int bmc150_accel_fifo_set_mode(struct bmc150_accel_data *data)
> > ret = regmap_write(data->regmap, BMC150_ACCEL_REG_FIFO_CONFIG0,
> > data->watermark);
> > if (ret < 0)
> > - dev_err(&data->client->dev, "Error writing reg_fifo_config0\n");
> > + dev_err(data->dev, "Error writing reg_fifo_config0\n");
> >
> > return ret;
> > }
> > @@ -1586,6 +1581,7 @@ static int bmc150_accel_probe(struct i2c_client *client,
> > int ret;
> > const char *name = NULL;
> > int chip_id = 0;
> > + struct device *dev;
> >
> > indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
> > if (!indio_dev)
> > @@ -1593,12 +1589,13 @@ static int bmc150_accel_probe(struct i2c_client *client,
> >
> > data = iio_priv(indio_dev);
> > i2c_set_clientdata(client, indio_dev);
> > - data->client = client;
> > data->dev = &client->dev;
> > + dev = &client->dev;
> > + data->irq = client->irq;
> >
> > data->regmap = devm_regmap_init_i2c(client, &bmc150_i2c_regmap_conf);
> > if (IS_ERR(data->regmap)) {
> > - dev_err(&client->dev, "Failed to initialize i2c regmap\n");
> > + dev_err(dev, "Failed to initialize i2c regmap\n");
> > return PTR_ERR(data->regmap);
> > }
> >
> > @@ -1607,8 +1604,8 @@ static int bmc150_accel_probe(struct i2c_client *client,
> > chip_id = id->driver_data;
> > }
> >
> > - if (ACPI_HANDLE(&client->dev))
> > - name = bmc150_accel_match_acpi_device(&client->dev, &chip_id);
> > + if (ACPI_HANDLE(dev))
> > + name = bmc150_accel_match_acpi_device(dev, &chip_id);
> >
> > data->chip_info = &bmc150_accel_chip_info_tbl[chip_id];
> >
> > @@ -1618,7 +1615,7 @@ static int bmc150_accel_probe(struct i2c_client *client,
> >
> > mutex_init(&data->mutex);
> >
> > - indio_dev->dev.parent = &client->dev;
> > + indio_dev->dev.parent = dev;
> > indio_dev->channels = data->chip_info->channels;
> > indio_dev->num_channels = data->chip_info->num_channels;
> > indio_dev->name = name;
> > @@ -1630,16 +1627,16 @@ static int bmc150_accel_probe(struct i2c_client *client,
> > bmc150_accel_trigger_handler,
> > &bmc150_accel_buffer_ops);
> > if (ret < 0) {
> > - dev_err(&client->dev, "Failed: iio triggered buffer setup\n");
> > + dev_err(data->dev, "Failed: iio triggered buffer setup\n");
> > return ret;
> > }
> >
> > - if (client->irq <= 0)
> > - client->irq = bmc150_accel_gpio_probe(client, data);
> > + if (data->irq <= 0)
> > + data->irq = bmc150_accel_gpio_probe(data);
> >
> > - if (client->irq > 0) {
> > + if (data->irq > 0) {
> > ret = devm_request_threaded_irq(
> > - &client->dev, client->irq,
> > + data->dev, data->irq,
> > bmc150_accel_irq_handler,
> > bmc150_accel_irq_thread_handler,
> > IRQF_TRIGGER_RISING,
> > @@ -1657,7 +1654,7 @@ static int bmc150_accel_probe(struct i2c_client *client,
> > ret = regmap_write(data->regmap, BMC150_ACCEL_REG_INT_RST_LATCH,
> > BMC150_ACCEL_INT_MODE_LATCH_RESET);
> > if (ret < 0) {
> > - dev_err(&data->client->dev, "Error writing reg_int_rst_latch\n");
> > + dev_err(data->dev, "Error writing reg_int_rst_latch\n");
> > goto err_buffer_cleanup;
> > }
> >
> > @@ -1678,18 +1675,17 @@ static int bmc150_accel_probe(struct i2c_client *client,
> >
> > ret = iio_device_register(indio_dev);
> > if (ret < 0) {
> > - dev_err(&client->dev, "Unable to register iio device\n");
> > + dev_err(data->dev, "Unable to register iio device\n");
> > goto err_trigger_unregister;
> > }
> >
> > - ret = pm_runtime_set_active(&client->dev);
> > + ret = pm_runtime_set_active(dev);
> > if (ret)
> > goto err_iio_unregister;
> >
> > - pm_runtime_enable(&client->dev);
> > - pm_runtime_set_autosuspend_delay(&client->dev,
> > - BMC150_AUTO_SUSPEND_DELAY_MS);
> > - pm_runtime_use_autosuspend(&client->dev);
> > + pm_runtime_enable(dev);
> > + pm_runtime_set_autosuspend_delay(dev, BMC150_AUTO_SUSPEND_DELAY_MS);
> > + pm_runtime_use_autosuspend(dev);
> >
> > return 0;
> >
> > @@ -1708,9 +1704,9 @@ static int bmc150_accel_remove(struct i2c_client *client)
> > struct iio_dev *indio_dev = i2c_get_clientdata(client);
> > struct bmc150_accel_data *data = iio_priv(indio_dev);
> >
> > - pm_runtime_disable(&client->dev);
> > - pm_runtime_set_suspended(&client->dev);
> > - pm_runtime_put_noidle(&client->dev);
> > + pm_runtime_disable(data->dev);
> > + pm_runtime_set_suspended(data->dev);
> > + pm_runtime_put_noidle(data->dev);
> >
> > iio_device_unregister(indio_dev);
> >
> > @@ -1728,7 +1724,7 @@ static int bmc150_accel_remove(struct i2c_client *client)
> > #ifdef CONFIG_PM_SLEEP
> > static int bmc150_accel_suspend(struct device *dev)
> > {
> > - struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
> > + struct iio_dev *indio_dev = dev_get_drvdata(dev);
> > struct bmc150_accel_data *data = iio_priv(indio_dev);
> >
> > mutex_lock(&data->mutex);
> > @@ -1740,7 +1736,7 @@ static int bmc150_accel_suspend(struct device *dev)
> >
> > static int bmc150_accel_resume(struct device *dev)
> > {
> > - struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
> > + struct iio_dev *indio_dev = dev_get_drvdata(dev);
> > struct bmc150_accel_data *data = iio_priv(indio_dev);
> >
> > mutex_lock(&data->mutex);
> > @@ -1756,11 +1752,11 @@ static int bmc150_accel_resume(struct device *dev)
> > #ifdef CONFIG_PM
> > static int bmc150_accel_runtime_suspend(struct device *dev)
> > {
> > - struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
> > + struct iio_dev *indio_dev = dev_get_drvdata(dev);
> > struct bmc150_accel_data *data = iio_priv(indio_dev);
> > int ret;
> >
> > - dev_dbg(&data->client->dev, __func__);
> > + dev_dbg(data->dev, __func__);
> > ret = bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_SUSPEND, 0);
> > if (ret < 0)
> > return -EAGAIN;
> > @@ -1770,12 +1766,12 @@ static int bmc150_accel_runtime_suspend(struct device *dev)
> >
> > static int bmc150_accel_runtime_resume(struct device *dev)
> > {
> > - struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
> > + struct iio_dev *indio_dev = dev_get_drvdata(dev);
> > struct bmc150_accel_data *data = iio_priv(indio_dev);
> > int ret;
> > int sleep_val;
> >
> > - dev_dbg(&data->client->dev, __func__);
> > + dev_dbg(data->dev, __func__);
> >
> > ret = bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_NORMAL, 0);
> > if (ret < 0)
> >
>
>
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
On Sat, Aug 15, 2015 at 02:41:29PM +0100, Jonathan Cameron wrote:
> On 12/08/15 11:12, Markus Pargmann wrote:
> > Signed-off-by: Markus Pargmann <[email protected]>
> There are a few bits in here following through from earlier
> patches that I haven't bothered mentioning as you'll have fixed
> them already before this split patch).
>
> Two more bits inline. Nothing major though.
>
> Jonathan
> > ---
> > drivers/iio/accel/Kconfig | 22 +++--
> > drivers/iio/accel/Makefile | 3 +-
> > .../accel/{bmc150-accel.c => bmc150-accel-core.c} | 95 ++++---------------
> > drivers/iio/accel/bmc150-accel-i2c.c | 101 +++++++++++++++++++++
> > drivers/iio/accel/bmc150-accel.h | 21 +++++
> > 5 files changed, 156 insertions(+), 86 deletions(-)
> > rename drivers/iio/accel/{bmc150-accel.c => bmc150-accel-core.c} (95%)
> > create mode 100644 drivers/iio/accel/bmc150-accel-i2c.c
> > create mode 100644 drivers/iio/accel/bmc150-accel.h
> >
> > diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
> > index 01dd03d194d1..c63e981c38ff 100644
> > --- a/drivers/iio/accel/Kconfig
> > +++ b/drivers/iio/accel/Kconfig
> > @@ -18,22 +18,30 @@ config BMA180
> > module will be called bma180.
> >
> > config BMC150_ACCEL
> > - tristate "Bosch BMC150 Accelerometer Driver"
> > - depends on I2C
> > - select IIO_BUFFER
> > - select IIO_TRIGGERED_BUFFER
> > + bool "Bosch BMC150 Accelerometer Driver"
> > select REGMAP
> > - select REGMAP_I2C
> > help
> > Say yes here to build support for the following Bosch accelerometers:
> > BMC150, BMI055, BMA250E, BMA222E, BMA255, BMA280.
> >
> > - Currently this only supports the device via an i2c interface.
> > -
> > This is a combo module with both accelerometer and magnetometer.
> > This driver is only implementing accelerometer part, which has
> > its own address and register map.
> This approach does lead to a proliferation of complexity (to the
> person configuring the kernel build). I prefer the approach the
> ST accel driver for example takes, in which the SPI or I2C drivers
> are built depending on whether the relevant dependencies are present
> and the core driver is selected.
Yes. I will fix this the same way as the other series (bmg160).
> >
> > +if BMC150_ACCEL
> > +
> > +config BMC150_ACCEL_I2C
> > + tristate "I2C support"
> > + depends on I2C
> > + select IIO_BUFFER
> > + select IIO_TRIGGERED_BUFFER
> > + select REGMAP_I2C
> > + help
> > + Say yes here to build support for I2C communication with the
> > + mentioned accelerometer.
> > +
> > +endif
> > +
> > config HID_SENSOR_ACCEL_3D
> > depends on HID_SENSOR_HUB
> > select IIO_BUFFER
> > diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile
> > index ebd2675b2a02..5ef8bdbad092 100644
> > --- a/drivers/iio/accel/Makefile
> > +++ b/drivers/iio/accel/Makefile
> > @@ -4,7 +4,8 @@
> >
> > # When adding new entries keep the list in alphabetical order
> > obj-$(CONFIG_BMA180) += bma180.o
> > -obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel.o
> > +obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o
> > +obj-$(CONFIG_BMC150_ACCEL_I2C) += bmc150-accel-i2c.o
> > obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o
> > obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o
> > obj-$(CONFIG_KXSD9) += kxsd9.o
> > diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel-core.c
> > similarity index 95%
> > rename from drivers/iio/accel/bmc150-accel.c
> > rename to drivers/iio/accel/bmc150-accel-core.c
> > index d75e1b0aa7e9..8cf2786dd433 100644
> > --- a/drivers/iio/accel/bmc150-accel.c
> > +++ b/drivers/iio/accel/bmc150-accel-core.c
> > @@ -37,6 +37,8 @@
> > #include <linux/iio/triggered_buffer.h>
> > #include <linux/regmap.h>
> >
> > +#include "bmc150-accel.h"
> > +
> > #define BMC150_ACCEL_DRV_NAME "bmc150_accel"
> > #define BMC150_ACCEL_IRQ_NAME "bmc150_accel_event"
> > #define BMC150_ACCEL_GPIO_NAME "bmc150_accel_int"
> > @@ -187,7 +189,6 @@ enum bmc150_accel_trigger_id {
> > struct bmc150_accel_data {
> > struct regmap *regmap;
> > struct device *dev;
> At least from how diff is listing it, looks like you've just
> moved this down the struct? Why?
No reason, will fix it.
Thanks,
Markus
> > - int irq;
> > struct bmc150_accel_interrupt interrupts[BMC150_ACCEL_INTERRUPTS];
> > atomic_t active_intr;
> > struct bmc150_accel_trigger triggers[BMC150_ACCEL_TRIGGERS];
> > @@ -201,6 +202,7 @@ struct bmc150_accel_data {
> > int ev_enable_state;
> > int64_t timestamp, old_timestamp; /* Only used in hw fifo mode. */
> > const struct bmc150_accel_chip_info *chip_info;
> > + int irq;
> > };
> >
> > static const struct {
> > @@ -1076,15 +1078,6 @@ static const struct iio_chan_spec bmc150_accel_channels[] =
> > static const struct iio_chan_spec bma280_accel_channels[] =
> > BMC150_ACCEL_CHANNELS(14);
> >
> > -enum {
> > - bmc150,
> > - bmi055,
> > - bma255,
> > - bma250e,
> > - bma222e,
> > - bma280,
> > -};
> > -
> > static const struct bmc150_accel_chip_info bmc150_accel_chip_info_tbl[] = {
> > [bmc150] = {
> > .chip_id = 0xFA,
> > @@ -1573,36 +1566,22 @@ static const struct iio_buffer_setup_ops bmc150_accel_buffer_ops = {
> > .postdisable = bmc150_accel_buffer_postdisable,
> > };
> >
> > -static int bmc150_accel_probe(struct i2c_client *client,
> > - const struct i2c_device_id *id)
> > +int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq,
> > + const char *name, int chip_id, bool block_supported)
> > {
> > struct bmc150_accel_data *data;
> > struct iio_dev *indio_dev;
> > int ret;
> > - const char *name = NULL;
> > - int chip_id = 0;
> > - struct device *dev;
> >
> > - indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
> > + indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
> > if (!indio_dev)
> > return -ENOMEM;
> >
> > data = iio_priv(indio_dev);
> > - i2c_set_clientdata(client, indio_dev);
> > - data->dev = &client->dev;
> > - dev = &client->dev;
> > - data->irq = client->irq;
> > -
> > - data->regmap = devm_regmap_init_i2c(client, &bmc150_i2c_regmap_conf);
> > - if (IS_ERR(data->regmap)) {
> > - dev_err(dev, "Failed to initialize i2c regmap\n");
> > - return PTR_ERR(data->regmap);
> > - }
> > -
> > - if (id) {
> > - name = id->name;
> > - chip_id = id->driver_data;
> > - }
> > + dev_set_drvdata(dev, indio_dev);
> > + data->dev = dev;
> > + data->irq = irq;
> > + data->regmap = regmap;
> >
> > if (ACPI_HANDLE(dev))
> > name = bmc150_accel_match_acpi_device(dev, &chip_id);
> > @@ -1664,9 +1643,7 @@ static int bmc150_accel_probe(struct i2c_client *client,
> > if (ret)
> > goto err_buffer_cleanup;
> >
> > - if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) ||
> > - i2c_check_functionality(client->adapter,
> > - I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
> > + if (block_supported) {
> > indio_dev->modes |= INDIO_BUFFER_SOFTWARE;
> > indio_dev->info = &bmc150_accel_info_fifo;
> > indio_dev->buffer->attrs = bmc150_accel_fifo_attributes;
> > @@ -1675,7 +1652,7 @@ static int bmc150_accel_probe(struct i2c_client *client,
> >
> > ret = iio_device_register(indio_dev);
> > if (ret < 0) {
> > - dev_err(data->dev, "Unable to register iio device\n");
> > + dev_err(dev, "Unable to register iio device\n");
> > goto err_trigger_unregister;
> > }
> >
> > @@ -1698,10 +1675,11 @@ err_buffer_cleanup:
> >
> > return ret;
> > }
> > +EXPORT_SYMBOL_GPL(bmc150_accel_core_probe);
> >
> > -static int bmc150_accel_remove(struct i2c_client *client)
> > +int bmc150_accel_core_remove(struct device *dev)
> > {
> > - struct iio_dev *indio_dev = i2c_get_clientdata(client);
> > + struct iio_dev *indio_dev = dev_get_drvdata(dev);
> > struct bmc150_accel_data *data = iio_priv(indio_dev);
> >
> > pm_runtime_disable(data->dev);
> > @@ -1720,6 +1698,7 @@ static int bmc150_accel_remove(struct i2c_client *client)
> >
> > return 0;
> > }
> > +EXPORT_SYMBOL_GPL(bmc150_accel_core_remove);
> >
> > #ifdef CONFIG_PM_SLEEP
> > static int bmc150_accel_suspend(struct device *dev)
> > @@ -1790,48 +1769,8 @@ static int bmc150_accel_runtime_resume(struct device *dev)
> > }
> > #endif
> >
> > -static const struct dev_pm_ops bmc150_accel_pm_ops = {
> > +const struct dev_pm_ops bmc150_accel_pm_ops = {
> > SET_SYSTEM_SLEEP_PM_OPS(bmc150_accel_suspend, bmc150_accel_resume)
> > SET_RUNTIME_PM_OPS(bmc150_accel_runtime_suspend,
> > bmc150_accel_runtime_resume, NULL)
> > };
> > -
> > -static const struct acpi_device_id bmc150_accel_acpi_match[] = {
> > - {"BSBA0150", bmc150},
> > - {"BMC150A", bmc150},
> > - {"BMI055A", bmi055},
> > - {"BMA0255", bma255},
> > - {"BMA250E", bma250e},
> > - {"BMA222E", bma222e},
> > - {"BMA0280", bma280},
> > - { },
> > -};
> > -MODULE_DEVICE_TABLE(acpi, bmc150_accel_acpi_match);
> > -
> > -static const struct i2c_device_id bmc150_accel_id[] = {
> > - {"bmc150_accel", bmc150},
> > - {"bmi055_accel", bmi055},
> > - {"bma255", bma255},
> > - {"bma250e", bma250e},
> > - {"bma222e", bma222e},
> > - {"bma280", bma280},
> > - {}
> > -};
> > -
> > -MODULE_DEVICE_TABLE(i2c, bmc150_accel_id);
> > -
> > -static struct i2c_driver bmc150_accel_driver = {
> > - .driver = {
> > - .name = BMC150_ACCEL_DRV_NAME,
> > - .acpi_match_table = ACPI_PTR(bmc150_accel_acpi_match),
> > - .pm = &bmc150_accel_pm_ops,
> > - },
> > - .probe = bmc150_accel_probe,
> > - .remove = bmc150_accel_remove,
> > - .id_table = bmc150_accel_id,
> > -};
> > -module_i2c_driver(bmc150_accel_driver);
> > -
> > -MODULE_AUTHOR("Srinivas Pandruvada <[email protected]>");
> > -MODULE_LICENSE("GPL v2");
> > -MODULE_DESCRIPTION("BMC150 accelerometer driver");
> > diff --git a/drivers/iio/accel/bmc150-accel-i2c.c b/drivers/iio/accel/bmc150-accel-i2c.c
> > new file mode 100644
> > index 000000000000..7e036e2eb077
> > --- /dev/null
> > +++ b/drivers/iio/accel/bmc150-accel-i2c.c
> > @@ -0,0 +1,101 @@
> > +/*
> > + * 3-axis accelerometer driver supporting following I2C Bosch-Sensortec chips:
> > + * - BMC150
> > + * - BMI055
> > + * - BMA255
> > + * - BMA250E
> > + * - BMA222E
> > + * - BMA280
> > + *
> > + * Copyright (c) 2014, Intel Corporation.
> > + *
> > + * This program is free software; you can redistribute it and/or modify it
> > + * under the terms and conditions of the GNU General Public License,
> > + * version 2, as published by the Free Software Foundation.
> > + *
> > + * This program is distributed in the hope it will be useful, but WITHOUT
> > + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> > + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
> > + * more details.
> > + */
> > +
> > +#include <linux/device.h>
> > +#include <linux/mod_devicetable.h>
> > +#include <linux/i2c.h>
> > +#include <linux/module.h>
> > +#include <linux/acpi.h>
> > +#include <linux/regmap.h>
> > +
> > +#include "bmc150-accel.h"
> > +
> > +static const struct regmap_config bmc150_i2c_regmap_conf = {
> > + .reg_bits = 8,
> > + .val_bits = 8,
> > +
> > + .use_single_rw = true,
> > + .cache_type = REGCACHE_NONE,
> > +};
> > +
> > +static int bmc150_accel_probe(struct i2c_client *client,
> > + const struct i2c_device_id *id)
> > +{
> > + struct regmap *regmap;
> > + bool block_supported =
> > + i2c_check_functionality(client->adapter, I2C_FUNC_I2C) ||
> > + i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK);
> > +
> > + regmap = devm_regmap_init_i2c(client, &bmc150_i2c_regmap_conf);
> > + if (IS_ERR(regmap)) {
> > + dev_err(&client->dev, "Failed to initialize i2c regmap\n");
> > + return PTR_ERR(regmap);
> > + }
> > +
> > + return bmc150_accel_core_probe(&client->dev, regmap, client->irq,
> > + id->name, id->driver_data,
> > + block_supported);
> > +}
> > +
> > +static int bmc150_accel_remove(struct i2c_client *client)
> > +{
> > + return bmc150_accel_core_remove(&client->dev);
> > +}
> > +
> > +static const struct acpi_device_id bmc150_accel_acpi_match[] = {
> > + {"BSBA0150", bmc150},
> > + {"BMC150A", bmc150},
> > + {"BMI055A", bmi055},
> > + {"BMA0255", bma255},
> > + {"BMA250E", bma250e},
> > + {"BMA222E", bma222e},
> > + {"BMA0280", bma280},
> > + { },
> > +};
> > +MODULE_DEVICE_TABLE(acpi, bmc150_accel_acpi_match);
> > +
> > +static const struct i2c_device_id bmc150_accel_id[] = {
> > + {"bmc150_accel", bmc150},
> > + {"bmi055_accel", bmi055},
> > + {"bma255", bma255},
> > + {"bma250e", bma250e},
> > + {"bma222e", bma222e},
> > + {"bma280", bma280},
> > + {}
> > +};
> > +
> > +MODULE_DEVICE_TABLE(i2c, bmc150_accel_id);
> > +
> > +static struct i2c_driver bmc150_accel_driver = {
> > + .driver = {
> > + .name = "bmc150_accel_i2c",
> > + .acpi_match_table = ACPI_PTR(bmc150_accel_acpi_match),
> > + .pm = &bmc150_accel_pm_ops,
> > + },
> > + .probe = bmc150_accel_probe,
> > + .remove = bmc150_accel_remove,
> > + .id_table = bmc150_accel_id,
> > +};
> > +module_i2c_driver(bmc150_accel_driver);
> > +
> > +MODULE_AUTHOR("Srinivas Pandruvada <[email protected]>");
> > +MODULE_LICENSE("GPL v2");
> > +MODULE_DESCRIPTION("BMC150 I2C accelerometer driver");
> > diff --git a/drivers/iio/accel/bmc150-accel.h b/drivers/iio/accel/bmc150-accel.h
> > new file mode 100644
> > index 000000000000..988b57573d0c
> > --- /dev/null
> > +++ b/drivers/iio/accel/bmc150-accel.h
> > @@ -0,0 +1,21 @@
> > +#ifndef _BMC150_ACCEL_H_
> > +#define _BMC150_ACCEL_H_
> > +
> > +struct regmap;
> > +
> > +enum {
> > + bmc150,
> > + bmi055,
> > + bma255,
> > + bma250e,
> > + bma222e,
> > + bma280,
> > +};
> > +
> > +int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq,
> > + const char *name, int chip_id,
> > + bool block_supported);
> > +int bmc150_accel_core_remove(struct device *dev);
> > +extern const struct dev_pm_ops bmc150_accel_pm_ops;
> > +
> > +#endif /* _BMC150_ACCEL_H_ */
> >
>
>
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
On Wed, Aug 12, 2015 at 01:03:00PM +0100, Mark Brown wrote:
> On Wed, Aug 12, 2015 at 12:12:45PM +0200, Markus Pargmann wrote:
>
> > + .use_single_rw = false,
> > + .cache_type = REGCACHE_NONE,
> > +};
>
> No need to initialise defaults.
Thanks, removed those.
Best regards,
Markus
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
On Sat, Aug 15, 2015 at 02:47:20PM +0100, Jonathan Cameron wrote:
> On 12/08/15 11:12, Markus Pargmann wrote:
> > Add a simple SPI driver which initializes the spi regmap for the bmc150
> > core driver.
> >
> > Signed-off-by: Markus Pargmann <[email protected]>
> 1 thing inline, plus the change of kconfig approach suggested for the
> previous patch.
>
> Otherwise, looks fine to me.
>
> Srinivas, over to you for the next version :) (unless you are feeling
> enthusiastic and want to take a look at this one)
> > ---
> > drivers/iio/accel/Kconfig | 10 +++++
> > drivers/iio/accel/Makefile | 1 +
> > drivers/iio/accel/bmc150-accel-spi.c | 86 ++++++++++++++++++++++++++++++++++++
> > 3 files changed, 97 insertions(+)
> > create mode 100644 drivers/iio/accel/bmc150-accel-spi.c
> >
> > diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
> > index c63e981c38ff..bdb42069a767 100644
> > --- a/drivers/iio/accel/Kconfig
> > +++ b/drivers/iio/accel/Kconfig
> > @@ -40,6 +40,16 @@ config BMC150_ACCEL_I2C
> > Say yes here to build support for I2C communication with the
> > mentioned accelerometer.
> >
> > +config BMC150_ACCEL_SPI
> > + tristate "SPI support"
> > + depends on SPI
> > + select IIO_BUFFER
> > + select IIO_TRIGGERED_BUFFER
> > + select REGMAP_SPI
> > + help
> > + Say yes here to build support for SPI communication with the
> > + mentioned accelerometer.
> If you move to the config approach I suggested earlier, these options
> are hidden away avoiding the need for a help message ;)
Yes.
> > +
> > endif
> >
> > config HID_SENSOR_ACCEL_3D
> > diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile
> > index 5ef8bdbad092..e579e93bf022 100644
> > --- a/drivers/iio/accel/Makefile
> > +++ b/drivers/iio/accel/Makefile
> > @@ -6,6 +6,7 @@
> > obj-$(CONFIG_BMA180) += bma180.o
> > obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o
> > obj-$(CONFIG_BMC150_ACCEL_I2C) += bmc150-accel-i2c.o
> > +obj-$(CONFIG_BMC150_ACCEL_SPI) += bmc150-accel-spi.o
> > obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o
> > obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o
> > obj-$(CONFIG_KXSD9) += kxsd9.o
> > diff --git a/drivers/iio/accel/bmc150-accel-spi.c b/drivers/iio/accel/bmc150-accel-spi.c
> > new file mode 100644
> > index 000000000000..c13fd2aa5f34
> > --- /dev/null
> > +++ b/drivers/iio/accel/bmc150-accel-spi.c
> > @@ -0,0 +1,86 @@
> > +/*
> > + * 3-axis accelerometer driver supporting following I2C Bosch-Sensortec chips:
> Umm. Read the line above? Spot the obvious minor point ;)
Oh yes. Thanks.
Best regards,
Markus
>
> > + * - BMC150
> > + * - BMI055
> > + * - BMA255
> > + * - BMA250E
> > + * - BMA222E
> > + * - BMA280
> > + *
> > + * Copyright (c) 2014, Intel Corporation.
> > + *
> > + * This program is free software; you can redistribute it and/or modify it
> > + * under the terms and conditions of the GNU General Public License,
> > + * version 2, as published by the Free Software Foundation.
> > + *
> > + * This program is distributed in the hope it will be useful, but WITHOUT
> > + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> > + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
> > + * more details.
> > + */
> > +
> > +#include <linux/device.h>
> > +#include <linux/mod_devicetable.h>
> > +#include <linux/module.h>
> > +#include <linux/acpi.h>
> > +#include <linux/regmap.h>
> > +#include <linux/spi/spi.h>
> > +
> > +#include "bmc150-accel.h"
> > +
> > +static const struct regmap_config bmc150_spi_regmap_conf = {
> > + .reg_bits = 8,
> > + .val_bits = 8,
> > + .max_register = 0x3f,
> > +
> > + .use_single_rw = false,
> > + .cache_type = REGCACHE_NONE,
> > +};
> > +
> > +static int bmc150_accel_probe(struct spi_device *spi)
> > +{
> > + struct regmap *regmap;
> > + const struct spi_device_id *id = spi_get_device_id(spi);
> > +
> > + regmap = devm_regmap_init_spi(spi, &bmc150_spi_regmap_conf);
> > + if (IS_ERR(regmap)) {
> > + dev_err(&spi->dev, "Failed to initialize spi regmap\n");
> > + return PTR_ERR(regmap);
> > + }
> > +
> > + return bmc150_accel_core_probe(&spi->dev, regmap, spi->irq,
> > + id->name, id->driver_data, true);
> > +}
> > +
> > +static int bmc150_accel_remove(struct spi_device *spi)
> > +{
> > + return bmc150_accel_core_remove(&spi->dev);
> > +}
> > +
> > +static const struct spi_device_id bmc150_accel_id[] = {
> > + {"bmc150_accel", bmc150},
> > + {"bmi055_accel", bmi055},
> > + {"bma255", bma255},
> > + {"bma250e", bma250e},
> > + {"bma222e", bma222e},
> > + {"bma280", bma280},
> > + {}
> > +};
> > +
> > +MODULE_DEVICE_TABLE(spi, bmc150_accel_id);
> > +
> > +static struct spi_driver bmc150_accel_driver = {
> > + .driver = {
> > + .name = "bmc150_accel_spi",
> > + .acpi_match_table = ACPI_PTR(bmc150_accel_acpi_match),
> > + .pm = &bmc150_accel_pm_ops,
> > + },
> > + .probe = bmc150_accel_probe,
> > + .remove = bmc150_accel_remove,
> > + .id_table = bmc150_accel_id,
> > +};
> > +module_spi_driver(bmc150_accel_driver);
> > +
> > +MODULE_AUTHOR("Markus Pargmann <[email protected]>");
> > +MODULE_LICENSE("GPL v2");
> > +MODULE_DESCRIPTION("BMC150 SPI accelerometer driver");
> >
>
>
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |