2018-09-04 19:07:11

by Afonso Bordado

[permalink] [raw]
Subject: [PATCH v3 1/4] iio: gyro: add support for fxas21002c

FXAS21002C is a 3 axis gyroscope with integrated temperature sensor

Signed-off-by: Afonso Bordado <[email protected]>
---
Changes in v3
- Use unsigned int on regmap functions
- Remove the export of the regmap config
- Fix undefined behaviour on dev_err call
- Minor cleanups

Changes in v2
- Use ANSI C Comments
- Minor cleanups
- More dscriptive devicetree bindings

drivers/iio/gyro/Kconfig | 11 +
drivers/iio/gyro/Makefile | 1 +
drivers/iio/gyro/fxas21002c.c | 372 ++++++++++++++++++++++++++++++++++
3 files changed, 384 insertions(+)
create mode 100644 drivers/iio/gyro/fxas21002c.c

diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig
index 3126cf05e6b9..d71e33ea9fa4 100644
--- a/drivers/iio/gyro/Kconfig
+++ b/drivers/iio/gyro/Kconfig
@@ -73,6 +73,17 @@ config BMG160_SPI
tristate
select REGMAP_SPI

+config FXAS21002C
+ tristate "Freescale FXAS21002C Gyroscope"
+ depends on I2C
+ select REGMAP_I2C
+ help
+ Say yes here to build support for the Freescale FXAS21002C Gyroscope
+ driver connected via I2C.
+
+ This driver can also be built as a module. If so, the module
+ will be called fxas21002c.
+
config HID_SENSOR_GYRO_3D
depends on HID_SENSOR_HUB
select IIO_BUFFER
diff --git a/drivers/iio/gyro/Makefile b/drivers/iio/gyro/Makefile
index 295ec780c4eb..ec3e2aeae92a 100644
--- a/drivers/iio/gyro/Makefile
+++ b/drivers/iio/gyro/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_ADXRS450) += adxrs450.o
obj-$(CONFIG_BMG160) += bmg160_core.o
obj-$(CONFIG_BMG160_I2C) += bmg160_i2c.o
obj-$(CONFIG_BMG160_SPI) += bmg160_spi.o
+obj-$(CONFIG_FXAS21002C) += fxas21002c.o

obj-$(CONFIG_HID_SENSOR_GYRO_3D) += hid-sensor-gyro-3d.o

diff --git a/drivers/iio/gyro/fxas21002c.c b/drivers/iio/gyro/fxas21002c.c
new file mode 100644
index 000000000000..1668e6f3fe11
--- /dev/null
+++ b/drivers/iio/gyro/fxas21002c.c
@@ -0,0 +1,372 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * FXAS21002C - Digital Angular Rate Gyroscope driver
+ *
+ * Copyright (c) 2018, Afonso Bordado <[email protected]>
+ *
+ * IIO driver for FXAS21002C (7-bit I2C slave address 0x20 or 0x21).
+ * Datasheet: https://www.nxp.com/docs/en/data-sheet/FXAS21002.pdf
+ * TODO:
+ * ODR / Scale Support
+ * Devicetree
+ * Power management
+ * GPIO Reset
+ * Power supplies
+ * Mount Matrix
+ * LowPass/HighPass Filters
+ * Buffers
+ * Interrupts
+ * Alarms
+ * SPI Support
+ */
+
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+#define FXAS21002C_DRV_NAME "fxas21002c"
+
+#define FXAS21002C_MAX_TRANSITION_TIME_MS 61
+
+#define FXAS21002C_CHIP_ID 0xD7
+
+#define FXAS21002C_REG_STATUS 0x00
+#define FXAS21002C_REG_OUT_X_MSB 0x01
+#define FXAS21002C_REG_OUT_X_LSB 0x02
+#define FXAS21002C_REG_OUT_Y_MSB 0x03
+#define FXAS21002C_REG_OUT_Y_LSB 0x04
+#define FXAS21002C_REG_OUT_Z_MSB 0x05
+#define FXAS21002C_REG_OUT_Z_LSB 0x06
+#define FXAS21002C_REG_DR_STATUS 0x07
+#define FXAS21002C_REG_F_STATUS 0x08
+#define FXAS21002C_REG_F_SETUP 0x09
+#define FXAS21002C_REG_F_EVENT 0x0A
+#define FXAS21002C_REG_INT_SRC_FLAG 0x0B
+#define FXAS21002C_REG_WHO_AM_I 0x0C
+#define FXAS21002C_REG_CTRL_REG0 0x0D
+#define FXAS21002C_REG_RT_CFG 0x0E
+#define FXAS21002C_REG_RT_SRC 0x0F
+#define FXAS21002C_REG_RT_THS 0x10
+#define FXAS21002C_REG_RT_COUNT 0x11
+#define FXAS21002C_REG_TEMP 0x12
+
+#define FXAS21002C_REG_CTRL_REG1 0x13
+#define FXAS21002C_RST_BIT BIT(6)
+#define FXAS21002C_ACTIVE_BIT BIT(1)
+#define FXAS21002C_READY_BIT BIT(0)
+
+#define FXAS21002C_REG_CTRL_REG2 0x14
+#define FXAS21002C_REG_CTRL_REG3 0x15
+
+#define FXAS21002C_DEFAULT_ODR_HZ 800
+
+/* 0.0625 deg/s */
+#define FXAS21002C_DEFAULT_SENSITIVITY IIO_DEGREE_TO_RAD(62500)
+
+#define FXAS21002C_TEMP_SCALE 1000
+
+enum {
+ ID_FXAS21002C,
+};
+
+enum fxas21002c_operating_mode {
+ FXAS21002C_OM_BOOT,
+ FXAS21002C_OM_STANDBY,
+ FXAS21002C_OM_READY,
+ FXAS21002C_OM_ACTIVE,
+};
+
+struct fxas21002c_data {
+ struct i2c_client *client;
+ struct regmap *regmap;
+};
+
+static const struct regmap_range fxas21002c_writable_ranges[] = {
+ regmap_reg_range(FXAS21002C_REG_F_SETUP, FXAS21002C_REG_F_SETUP),
+ regmap_reg_range(FXAS21002C_REG_CTRL_REG0, FXAS21002C_REG_RT_CFG),
+ regmap_reg_range(FXAS21002C_REG_RT_THS, FXAS21002C_REG_RT_COUNT),
+ regmap_reg_range(FXAS21002C_REG_CTRL_REG1, FXAS21002C_REG_CTRL_REG3),
+};
+
+static const struct regmap_access_table fxas21002c_writable_table = {
+ .yes_ranges = fxas21002c_writable_ranges,
+ .n_yes_ranges = ARRAY_SIZE(fxas21002c_writable_ranges),
+};
+
+static const struct regmap_range fxas21002c_volatile_ranges[] = {
+ regmap_reg_range(FXAS21002C_REG_STATUS, FXAS21002C_REG_F_STATUS),
+ regmap_reg_range(FXAS21002C_REG_F_EVENT, FXAS21002C_REG_INT_SRC_FLAG),
+ regmap_reg_range(FXAS21002C_REG_RT_COUNT, FXAS21002C_REG_CTRL_REG1),
+};
+
+static const struct regmap_access_table fxas21002c_volatile_table = {
+ .yes_ranges = fxas21002c_volatile_ranges,
+ .n_yes_ranges = ARRAY_SIZE(fxas21002c_volatile_ranges),
+};
+
+const struct regmap_config fxas21002c_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = FXAS21002C_REG_CTRL_REG3,
+ /* We don't specify a .rd_table because everything is readable */
+ .wr_table = &fxas21002c_writable_table,
+ .volatile_table = &fxas21002c_volatile_table,
+};
+
+#define FXAS21002C_GYRO_CHAN(_axis) { \
+ .type = IIO_ANGL_VEL, \
+ .modified = 1, \
+ .channel2 = IIO_MOD_ ## _axis, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+ .address = FXAS21002C_REG_OUT_ ## _axis ## _MSB, \
+}
+
+static const struct iio_chan_spec fxas21002c_channels[] = {
+ {
+ .type = IIO_TEMP,
+ .address = FXAS21002C_REG_TEMP,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ },
+ FXAS21002C_GYRO_CHAN(X),
+ FXAS21002C_GYRO_CHAN(Y),
+ FXAS21002C_GYRO_CHAN(Z),
+ IIO_CHAN_SOFT_TIMESTAMP(3),
+};
+
+static int fxas21002c_set_operating_mode(struct fxas21002c_data *data,
+ enum fxas21002c_operating_mode om)
+{
+ int ret;
+ int mask;
+
+ switch (om) {
+ case FXAS21002C_OM_STANDBY:
+ mask = 0;
+ break;
+ case FXAS21002C_OM_READY:
+ mask = FXAS21002C_READY_BIT;
+ break;
+ case FXAS21002C_OM_ACTIVE:
+ mask = FXAS21002C_ACTIVE_BIT;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ ret = regmap_write(data->regmap, FXAS21002C_REG_CTRL_REG1, mask);
+ if (ret) {
+ dev_err(&data->client->dev,
+ "could not switch operating mode\n");
+ return ret;
+ }
+
+ msleep(FXAS21002C_MAX_TRANSITION_TIME_MS);
+
+ return 0;
+}
+
+static void fxas21002c_standby(void *_data)
+{
+ struct fxas21002c_data *data = _data;
+
+ fxas21002c_set_operating_mode(data, FXAS21002C_OM_STANDBY);
+}
+
+static int fxas21002c_reset(struct fxas21002c_data *data)
+{
+ int ret;
+
+ /*
+ * On issuing a Software Reset command over an I2C interface,
+ * the device immediately resets and does not send any
+ * acknowledgment (ACK) of the written byte to the Master.
+ *
+ * This is documented in table 46 on the datasheet. Due to this
+ * the write will fail with EREMOTEIO.
+ */
+ ret = regmap_write(data->regmap,
+ FXAS21002C_REG_CTRL_REG1, FXAS21002C_RST_BIT);
+
+ if (ret != -EREMOTEIO) {
+ dev_err(&data->client->dev, "could not reset device\n");
+ return ret;
+ }
+
+ regcache_mark_dirty(data->regmap);
+
+ /* Wait for device to boot up */
+ msleep(FXAS21002C_MAX_TRANSITION_TIME_MS);
+
+ return 0;
+}
+
+static int fxas21002c_verify_chip(struct fxas21002c_data *data)
+{
+ int ret;
+ unsigned int chip_id;
+
+ ret = regmap_read(data->regmap, FXAS21002C_REG_WHO_AM_I, &chip_id);
+ if (ret) {
+ dev_err(&data->client->dev, "could not read device id\n");
+ return ret;
+ }
+
+ if (chip_id != FXAS21002C_CHIP_ID) {
+ dev_err(&data->client->dev,
+ "unsupported chip id %02x\n", chip_id);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int fxas21002c_read_oneshot(struct fxas21002c_data *data,
+ struct iio_chan_spec const *chan, int *val)
+{
+ int ret;
+ __be16 bulk_raw;
+ unsigned int uval;
+
+ switch (chan->type) {
+ case IIO_ANGL_VEL:
+ ret = regmap_bulk_read(data->regmap, chan->address,
+ &bulk_raw, sizeof(bulk_raw));
+ if (ret)
+ return ret;
+
+ *val = sign_extend32(be16_to_cpu(bulk_raw), 15);
+ return IIO_VAL_INT;
+ case IIO_TEMP:
+ ret = regmap_read(data->regmap, chan->address, &uval);
+ if (ret)
+ return ret;
+
+ *val = sign_extend32(uval, 7);
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int fxas21002c_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int *val,
+ int *val2, long mask)
+{
+ struct fxas21002c_data *data = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ return fxas21002c_read_oneshot(data, chan, val);
+ case IIO_CHAN_INFO_SCALE:
+ switch (chan->type) {
+ case IIO_ANGL_VEL:
+ *val = 0;
+ *val2 = FXAS21002C_DEFAULT_SENSITIVITY;
+
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_TEMP:
+ *val = FXAS21002C_TEMP_SCALE;
+
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ if (chan->type != IIO_ANGL_VEL)
+ return -EINVAL;
+
+ *val = FXAS21002C_DEFAULT_ODR_HZ;
+
+ return IIO_VAL_INT;
+ }
+
+ return -EINVAL;
+}
+
+static const struct iio_info fxas21002c_info = {
+ .read_raw = fxas21002c_read_raw,
+};
+
+static int fxas21002c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int ret;
+ struct iio_dev *indio_dev;
+ struct fxas21002c_data *data;
+
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, indio_dev);
+ data = iio_priv(indio_dev);
+ data->client = client;
+
+ data->regmap = devm_regmap_init_i2c(client, &fxas21002c_regmap_config);
+ if (IS_ERR(data->regmap)) {
+ ret = PTR_ERR(data->regmap);
+ dev_err(&client->dev,
+ "Failed to allocate regmap, err: %d\n", ret);
+ return ret;
+ }
+
+ indio_dev->dev.parent = &client->dev;
+ indio_dev->channels = fxas21002c_channels;
+ indio_dev->num_channels = ARRAY_SIZE(fxas21002c_channels);
+ indio_dev->name = id->name;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->info = &fxas21002c_info;
+
+ ret = fxas21002c_verify_chip(data);
+ if (ret < 0)
+ return ret;
+
+ ret = fxas21002c_reset(data);
+ if (ret < 0)
+ return ret;
+
+ ret = fxas21002c_set_operating_mode(data, FXAS21002C_OM_ACTIVE);
+ if (ret < 0)
+ return ret;
+
+ ret = devm_add_action(&client->dev, fxas21002c_standby, data);
+ if (ret < 0) {
+ fxas21002c_standby(data);
+ dev_err(&client->dev, "failed to add standby action\n");
+ return ret;
+ }
+
+ ret = iio_device_register(indio_dev);
+ if (ret < 0)
+ dev_err(&client->dev, "failed to register iio device\n");
+
+ return ret;
+}
+
+static const struct i2c_device_id fxas21002c_id[] = {
+ {"fxas21002c", ID_FXAS21002C},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, fxas21002c_id);
+
+static struct i2c_driver fxas21002c_driver = {
+ .driver = {
+ .name = FXAS21002C_DRV_NAME,
+ },
+ .probe = fxas21002c_probe,
+ .id_table = fxas21002c_id,
+};
+
+module_i2c_driver(fxas21002c_driver);
+
+MODULE_AUTHOR("Afonso Bordado <[email protected]>");
+MODULE_DESCRIPTION("FXAS21002C Digital Angular Rate Gyroscope driver");
+MODULE_LICENSE("GPL v2");
--
2.18.0




2018-09-04 19:06:39

by Afonso Bordado

[permalink] [raw]
Subject: [PATCH v3 2/4] iio: gyro: add device tree support for fxas21002c

This patch adds device tree support for the fxas21002c driver, including
bindings.

Signed-off-by: Afonso Bordado <[email protected]>
---
.../bindings/iio/gyroscope/fsl,fxas21002c.txt | 35 +++++++++++++++++++
drivers/iio/gyro/fxas21002c.c | 10 +++++-
2 files changed, 44 insertions(+), 1 deletion(-)
create mode 100644 Documentation/devicetree/bindings/iio/gyroscope/fsl,fxas21002c.txt

diff --git a/Documentation/devicetree/bindings/iio/gyroscope/fsl,fxas21002c.txt b/Documentation/devicetree/bindings/iio/gyroscope/fsl,fxas21002c.txt
new file mode 100644
index 000000000000..5f02cfa5ac82
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/gyroscope/fsl,fxas21002c.txt
@@ -0,0 +1,35 @@
+* Freescale FXAS21002C Digital Angular Rate Gyroscope
+
+Required properties:
+
+ - compatible: must be "fsl,fxas21002c"
+ - reg : the I2C address of the sensor
+
+Optional properties:
+
+ - interrupt-parent : phandle to the parent interrupt controller.
+ see interrupt-controller/interrupts.txt
+ - interrupts : The first interrupt listed must be the one
+ connected to the INT1 pin, the second interrupt
+ listed must be the one connected to the INT2 pin.
+ The interrupts can be triggered on rising or falling
+ edges alike.
+ see interrupt-controller/interrupts.txt
+ - vdd-supply : The main voltage regulator
+ - iovdd-supply : The IO voltage regulator
+ see regulator/regulator.txt
+ - reset-gpios : GPIO used to reset the device.
+ see gpio/gpio.txt.
+ - mount-matrix : see iio/mount-matrix.txt
+
+Example:
+gyroscope@20 {
+ compatible = "fsl,fxas21002c";
+ reg = <0x20>;
+ reset-gpios = <&gpio0 2 0>;
+ vdd-supply = <&vref>;
+ iovdd-supply = <&vref2>;
+ interrupt-parent = <&foo>;
+ interrupts = <0 IRQ_TYPE_EDGE_RISING>,
+ <1 (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)>;
+};
diff --git a/drivers/iio/gyro/fxas21002c.c b/drivers/iio/gyro/fxas21002c.c
index 1668e6f3fe11..18b1f500dd3e 100644
--- a/drivers/iio/gyro/fxas21002c.c
+++ b/drivers/iio/gyro/fxas21002c.c
@@ -8,7 +8,6 @@
* Datasheet: https://www.nxp.com/docs/en/data-sheet/FXAS21002.pdf
* TODO:
* ODR / Scale Support
- * Devicetree
* Power management
* GPIO Reset
* Power supplies
@@ -350,6 +349,14 @@ static int fxas21002c_probe(struct i2c_client *client,
return ret;
}

+#ifdef CONFIG_OF
+static const struct of_device_id fxas21002c_of_ids[] = {
+ {.compatible = "fsl,fxas21002c"},
+ {}
+};
+MODULE_DEVICE_TABLE(of, fxas21002c_of_ids);
+#endif
+
static const struct i2c_device_id fxas21002c_id[] = {
{"fxas21002c", ID_FXAS21002C},
{}
@@ -360,6 +367,7 @@ MODULE_DEVICE_TABLE(i2c, fxas21002c_id);
static struct i2c_driver fxas21002c_driver = {
.driver = {
.name = FXAS21002C_DRV_NAME,
+ .of_match_table = of_match_ptr(fxas21002c_of_ids),
},
.probe = fxas21002c_probe,
.id_table = fxas21002c_id,
--
2.18.0



2018-09-04 19:06:41

by Afonso Bordado

[permalink] [raw]
Subject: [PATCH v3 3/4] iio: fxas21002c: add ODR/Scale support

This patch adds support for reading/writing ODR/Scale

We don't support the scale boost modes.

Signed-off-by: Afonso Bordado <[email protected]>
---
drivers/iio/gyro/fxas21002c.c | 161 +++++++++++++++++++++++++++++++---
1 file changed, 148 insertions(+), 13 deletions(-)

diff --git a/drivers/iio/gyro/fxas21002c.c b/drivers/iio/gyro/fxas21002c.c
index 18b1f500dd3e..7efef3156fa0 100644
--- a/drivers/iio/gyro/fxas21002c.c
+++ b/drivers/iio/gyro/fxas21002c.c
@@ -7,7 +7,7 @@
* IIO driver for FXAS21002C (7-bit I2C slave address 0x20 or 0x21).
* Datasheet: https://www.nxp.com/docs/en/data-sheet/FXAS21002.pdf
* TODO:
- * ODR / Scale Support
+ * Scale boost mode
* Power management
* GPIO Reset
* Power supplies
@@ -44,7 +44,10 @@
#define FXAS21002C_REG_F_EVENT 0x0A
#define FXAS21002C_REG_INT_SRC_FLAG 0x0B
#define FXAS21002C_REG_WHO_AM_I 0x0C
+
#define FXAS21002C_REG_CTRL_REG0 0x0D
+#define FXAS21002C_SCALE_MASK GENMASK(1, 0)
+
#define FXAS21002C_REG_RT_CFG 0x0E
#define FXAS21002C_REG_RT_SRC 0x0F
#define FXAS21002C_REG_RT_THS 0x10
@@ -56,14 +59,12 @@
#define FXAS21002C_ACTIVE_BIT BIT(1)
#define FXAS21002C_READY_BIT BIT(0)

+#define FXAS21002C_ODR_SHIFT 2
+#define FXAS21002C_ODR_MASK GENMASK(4, 2)
+
#define FXAS21002C_REG_CTRL_REG2 0x14
#define FXAS21002C_REG_CTRL_REG3 0x15

-#define FXAS21002C_DEFAULT_ODR_HZ 800
-
-/* 0.0625 deg/s */
-#define FXAS21002C_DEFAULT_SENSITIVITY IIO_DEGREE_TO_RAD(62500)
-
#define FXAS21002C_TEMP_SCALE 1000

enum {
@@ -82,6 +83,40 @@ struct fxas21002c_data {
struct regmap *regmap;
};

+enum fxas21002c_scale {
+ FXAS21002C_SCALE_62MDPS,
+ FXAS21002C_SCALE_31MDPS,
+ FXAS21002C_SCALE_15MDPS,
+ FXAS21002C_SCALE_7MDPS,
+};
+
+static const int fxas21002c_anglevel_scale_avail[4][2] = {
+ [FXAS21002C_SCALE_62MDPS] = { 0, IIO_DEGREE_TO_RAD(62500) },
+ [FXAS21002C_SCALE_31MDPS] = { 0, IIO_DEGREE_TO_RAD(31250) },
+ [FXAS21002C_SCALE_15MDPS] = { 0, IIO_DEGREE_TO_RAD(15625) },
+ [FXAS21002C_SCALE_7MDPS] = { 0, IIO_DEGREE_TO_RAD(7812) },
+};
+
+enum fxas21002c_odr {
+ FXAS21002C_ODR_800,
+ FXAS21002C_ODR_400,
+ FXAS21002C_ODR_200,
+ FXAS21002C_ODR_100,
+ FXAS21002C_ODR_50,
+ FXAS21002C_ODR_25,
+ FXAS21002C_ODR_12_5,
+};
+
+static const int fxas21002c_sample_freq_avail[7][2] = {
+ [FXAS21002C_ODR_800] = { 800, 0 },
+ [FXAS21002C_ODR_400] = { 400, 0 },
+ [FXAS21002C_ODR_200] = { 200, 0 },
+ [FXAS21002C_ODR_100] = { 100, 0 },
+ [FXAS21002C_ODR_50] = { 50, 0 },
+ [FXAS21002C_ODR_25] = { 25, 0 },
+ [FXAS21002C_ODR_12_5] = { 12, 500000 },
+};
+
static const struct regmap_range fxas21002c_writable_ranges[] = {
regmap_reg_range(FXAS21002C_REG_F_SETUP, FXAS21002C_REG_F_SETUP),
regmap_reg_range(FXAS21002C_REG_CTRL_REG0, FXAS21002C_REG_RT_CFG),
@@ -254,6 +289,49 @@ static int fxas21002c_read_oneshot(struct fxas21002c_data *data,
}
}

+static int fxas21002c_scale_read(struct fxas21002c_data *data, int *val,
+ int *val2)
+{
+ int ret;
+ unsigned int raw;
+
+ ret = regmap_read(data->regmap, FXAS21002C_REG_CTRL_REG0, &raw);
+ if (ret)
+ return ret;
+
+ raw &= FXAS21002C_SCALE_MASK;
+
+ *val = fxas21002c_anglevel_scale_avail[raw][0];
+ *val2 = fxas21002c_anglevel_scale_avail[raw][1];
+
+ return IIO_VAL_INT_PLUS_MICRO;
+}
+
+static int fxas21002c_odr_read(struct fxas21002c_data *data, int *val,
+ int *val2)
+{
+ int ret;
+ unsigned int raw;
+
+ ret = regmap_read(data->regmap, FXAS21002C_REG_CTRL_REG1, &raw);
+ if (ret)
+ return ret;
+
+ raw = (raw & FXAS21002C_ODR_MASK) >> FXAS21002C_ODR_SHIFT;
+
+ /*
+ * We don't use this mode but according to the datasheet its
+ * also a 12.5Hz
+ */
+ if (raw == 7)
+ raw = FXAS21002C_ODR_12_5;
+
+ *val = fxas21002c_sample_freq_avail[raw][0];
+ *val2 = fxas21002c_sample_freq_avail[raw][1];
+
+ return IIO_VAL_INT_PLUS_MICRO;
+}
+
static int fxas21002c_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int *val,
int *val2, long mask)
@@ -266,10 +344,7 @@ static int fxas21002c_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_ANGL_VEL:
- *val = 0;
- *val2 = FXAS21002C_DEFAULT_SENSITIVITY;
-
- return IIO_VAL_INT_PLUS_MICRO;
+ return fxas21002c_scale_read(data, val, val2);
case IIO_TEMP:
*val = FXAS21002C_TEMP_SCALE;

@@ -281,16 +356,76 @@ static int fxas21002c_read_raw(struct iio_dev *indio_dev,
if (chan->type != IIO_ANGL_VEL)
return -EINVAL;

- *val = FXAS21002C_DEFAULT_ODR_HZ;
-
- return IIO_VAL_INT;
+ return fxas21002c_odr_read(data, val, val2);
}

return -EINVAL;
}

+static int fxas21002c_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int val,
+ int val2, long mask)
+{
+ struct fxas21002c_data *data = iio_priv(indio_dev);
+ int ret = -EINVAL;
+ int i;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ for (i = 0; i < ARRAY_SIZE(fxas21002c_sample_freq_avail); i++) {
+ if (fxas21002c_sample_freq_avail[i][0] == val &&
+ fxas21002c_sample_freq_avail[i][1] == val2)
+ break;
+ }
+
+ if (i == ARRAY_SIZE(fxas21002c_sample_freq_avail))
+ break;
+
+ return regmap_update_bits(data->regmap,
+ FXAS21002C_REG_CTRL_REG1,
+ FXAS21002C_ODR_MASK,
+ i << FXAS21002C_ODR_SHIFT);
+ case IIO_CHAN_INFO_SCALE:
+ for (i = 0; i < ARRAY_SIZE(fxas21002c_anglevel_scale_avail);
+ i++) {
+ if (fxas21002c_anglevel_scale_avail[i][0] == val &&
+ fxas21002c_anglevel_scale_avail[i][1] == val2)
+ break;
+ }
+
+ if (i == ARRAY_SIZE(fxas21002c_anglevel_scale_avail))
+ break;
+
+ return regmap_update_bits(data->regmap,
+ FXAS21002C_REG_CTRL_REG0,
+ FXAS21002C_SCALE_MASK, i);
+ }
+
+ return ret;
+}
+
+static IIO_CONST_ATTR(anglevel_scale_available,
+ "0.001090831 " /* 62.5 mdps */
+ "0.000545415 " /* 31.25 mdps */
+ "0.000272708 " /* 15.625 mdps */
+ "0.000136354"); /* 7.8125 mdps */
+
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("800 400 200 100 50 25 12.5");
+
+static struct attribute *fxas21002c_attributes[] = {
+ &iio_const_attr_anglevel_scale_available.dev_attr.attr,
+ &iio_const_attr_sampling_frequency_available.dev_attr.attr,
+ NULL
+};
+
+static const struct attribute_group fxas21002c_attribute_group = {
+ .attrs = fxas21002c_attributes,
+};
+
static const struct iio_info fxas21002c_info = {
.read_raw = fxas21002c_read_raw,
+ .write_raw = fxas21002c_write_raw,
+ .attrs = &fxas21002c_attribute_group,
};

static int fxas21002c_probe(struct i2c_client *client,
--
2.18.0



2018-09-04 19:06:44

by Afonso Bordado

[permalink] [raw]
Subject: [PATCH v3 4/4] MAINTAINERS: add entry for fxas21002c gyro driver

Add entry for fxas21002c gyroscope driver and add myself as
maintainer of this driver.

Signed-off-by: Afonso Bordado <[email protected]>
---
MAINTAINERS | 7 +++++++
1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 2b7b24b145f0..faf5f41b1465 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5838,6 +5838,13 @@ L: [email protected]
S: Maintained
F: drivers/usb/gadget/udc/fsl*

+FREESCALE FXAS21002C
+M: Afonso Bordado <[email protected]>
+L: [email protected]
+S: Maintained
+F: drivers/iio/gyro/fxas21002.c
+F: Documentation/devicetree/bindings/iio/gyroscope/fsl,fxas21002c.txt
+
FREEVXFS FILESYSTEM
M: Christoph Hellwig <[email protected]>
W: ftp://ftp.openlinux.org/pub/people/hch/vxfs
--
2.18.0



2018-09-04 19:15:41

by Andy Shevchenko

[permalink] [raw]
Subject: Re: [PATCH v3 2/4] iio: gyro: add device tree support for fxas21002c

On Tue, Sep 4, 2018 at 10:06 PM Afonso Bordado <[email protected]> wrote:
>
> This patch adds device tree support for the fxas21002c driver, including
> bindings.
>
> Signed-off-by: Afonso Bordado <[email protected]>

> +#ifdef CONFIG_OF

> +#endif

Please, remove this ifdef...

> + .of_match_table = of_match_ptr(fxas21002c_of_ids),

...and do not use of_match_ptr() macro.

This prevents to use device on embedded ACPI enabled devices,

> },
> .probe = fxas21002c_probe,
> .id_table = fxas21002c_id,
> --
> 2.18.0
>
>


--
With Best Regards,
Andy Shevchenko

2018-09-04 19:18:37

by Andy Shevchenko

[permalink] [raw]
Subject: Re: [PATCH v3 4/4] MAINTAINERS: add entry for fxas21002c gyro driver

On Tue, Sep 4, 2018 at 10:07 PM Afonso Bordado <[email protected]> wrote:
>
> Add entry for fxas21002c gyroscope driver and add myself as
> maintainer of this driver.
>
> Signed-off-by: Afonso Bordado <[email protected]>
> ---
> MAINTAINERS | 7 +++++++
> 1 file changed, 7 insertions(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 2b7b24b145f0..faf5f41b1465 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -5838,6 +5838,13 @@ L: [email protected]
> S: Maintained
> F: drivers/usb/gadget/udc/fsl*
>
> +FREESCALE FXAS21002C
> +M: Afonso Bordado <[email protected]>
> +L: [email protected]
> +S: Maintained
> +F: drivers/iio/gyro/fxas21002.c
> +F: Documentation/devicetree/bindings/iio/gyroscope/fsl,fxas21002c.txt
> +

Must be sorted. I bet F followed by U, not otherwise.

> FREEVXFS FILESYSTEM
> M: Christoph Hellwig <[email protected]>
> W: ftp://ftp.openlinux.org/pub/people/hch/vxfs
> --
> 2.18.0
>
>


--
With Best Regards,
Andy Shevchenko

2018-09-04 19:20:39

by Andy Shevchenko

[permalink] [raw]
Subject: Re: [PATCH v3 1/4] iio: gyro: add support for fxas21002c

On Tue, Sep 4, 2018 at 10:08 PM Afonso Bordado <[email protected]> wrote:
>
> FXAS21002C is a 3 axis gyroscope with integrated temperature sensor
>
> Signed-off-by: Afonso Bordado <[email protected]>
> ---
> Changes in v3
> - Use unsigned int on regmap functions
> - Remove the export of the regmap config
> - Fix undefined behaviour on dev_err call
> - Minor cleanups
>
> Changes in v2
> - Use ANSI C Comments
> - Minor cleanups
> - More dscriptive devicetree bindings
>
> drivers/iio/gyro/Kconfig | 11 +
> drivers/iio/gyro/Makefile | 1 +
> drivers/iio/gyro/fxas21002c.c | 372 ++++++++++++++++++++++++++++++++++
> 3 files changed, 384 insertions(+)
> create mode 100644 drivers/iio/gyro/fxas21002c.c
>
> diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig
> index 3126cf05e6b9..d71e33ea9fa4 100644
> --- a/drivers/iio/gyro/Kconfig
> +++ b/drivers/iio/gyro/Kconfig
> @@ -73,6 +73,17 @@ config BMG160_SPI
> tristate
> select REGMAP_SPI
>
> +config FXAS21002C
> + tristate "Freescale FXAS21002C Gyroscope"
> + depends on I2C
> + select REGMAP_I2C
> + help
> + Say yes here to build support for the Freescale FXAS21002C Gyroscope
> + driver connected via I2C.
> +
> + This driver can also be built as a module. If so, the module
> + will be called fxas21002c.
> +
> config HID_SENSOR_GYRO_3D
> depends on HID_SENSOR_HUB
> select IIO_BUFFER
> diff --git a/drivers/iio/gyro/Makefile b/drivers/iio/gyro/Makefile
> index 295ec780c4eb..ec3e2aeae92a 100644
> --- a/drivers/iio/gyro/Makefile
> +++ b/drivers/iio/gyro/Makefile
> @@ -12,6 +12,7 @@ obj-$(CONFIG_ADXRS450) += adxrs450.o
> obj-$(CONFIG_BMG160) += bmg160_core.o
> obj-$(CONFIG_BMG160_I2C) += bmg160_i2c.o
> obj-$(CONFIG_BMG160_SPI) += bmg160_spi.o
> +obj-$(CONFIG_FXAS21002C) += fxas21002c.o
>
> obj-$(CONFIG_HID_SENSOR_GYRO_3D) += hid-sensor-gyro-3d.o
>
> diff --git a/drivers/iio/gyro/fxas21002c.c b/drivers/iio/gyro/fxas21002c.c
> new file mode 100644
> index 000000000000..1668e6f3fe11
> --- /dev/null
> +++ b/drivers/iio/gyro/fxas21002c.c
> @@ -0,0 +1,372 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * FXAS21002C - Digital Angular Rate Gyroscope driver
> + *
> + * Copyright (c) 2018, Afonso Bordado <[email protected]>
> + *
> + * IIO driver for FXAS21002C (7-bit I2C slave address 0x20 or 0x21).
> + * Datasheet: https://www.nxp.com/docs/en/data-sheet/FXAS21002.pdf
> + * TODO:
> + * ODR / Scale Support
> + * Devicetree
> + * Power management
> + * GPIO Reset
> + * Power supplies
> + * Mount Matrix
> + * LowPass/HighPass Filters
> + * Buffers
> + * Interrupts
> + * Alarms
> + * SPI Support
> + */

With this rather long TODO list it sounds like a staging candidate,
though if it allows us to use it in the shape provided by the change,
code looks good
Reviewed-by: Andy Shevchenko <[email protected]>

> +
> +#include <linux/i2c.h>
> +#include <linux/iio/iio.h>
> +#include <linux/iio/sysfs.h>
> +#include <linux/module.h>
> +#include <linux/regmap.h>
> +
> +#define FXAS21002C_DRV_NAME "fxas21002c"
> +
> +#define FXAS21002C_MAX_TRANSITION_TIME_MS 61
> +
> +#define FXAS21002C_CHIP_ID 0xD7
> +
> +#define FXAS21002C_REG_STATUS 0x00
> +#define FXAS21002C_REG_OUT_X_MSB 0x01
> +#define FXAS21002C_REG_OUT_X_LSB 0x02
> +#define FXAS21002C_REG_OUT_Y_MSB 0x03
> +#define FXAS21002C_REG_OUT_Y_LSB 0x04
> +#define FXAS21002C_REG_OUT_Z_MSB 0x05
> +#define FXAS21002C_REG_OUT_Z_LSB 0x06
> +#define FXAS21002C_REG_DR_STATUS 0x07
> +#define FXAS21002C_REG_F_STATUS 0x08
> +#define FXAS21002C_REG_F_SETUP 0x09
> +#define FXAS21002C_REG_F_EVENT 0x0A
> +#define FXAS21002C_REG_INT_SRC_FLAG 0x0B
> +#define FXAS21002C_REG_WHO_AM_I 0x0C
> +#define FXAS21002C_REG_CTRL_REG0 0x0D
> +#define FXAS21002C_REG_RT_CFG 0x0E
> +#define FXAS21002C_REG_RT_SRC 0x0F
> +#define FXAS21002C_REG_RT_THS 0x10
> +#define FXAS21002C_REG_RT_COUNT 0x11
> +#define FXAS21002C_REG_TEMP 0x12
> +
> +#define FXAS21002C_REG_CTRL_REG1 0x13
> +#define FXAS21002C_RST_BIT BIT(6)
> +#define FXAS21002C_ACTIVE_BIT BIT(1)
> +#define FXAS21002C_READY_BIT BIT(0)
> +
> +#define FXAS21002C_REG_CTRL_REG2 0x14
> +#define FXAS21002C_REG_CTRL_REG3 0x15
> +
> +#define FXAS21002C_DEFAULT_ODR_HZ 800
> +
> +/* 0.0625 deg/s */
> +#define FXAS21002C_DEFAULT_SENSITIVITY IIO_DEGREE_TO_RAD(62500)
> +
> +#define FXAS21002C_TEMP_SCALE 1000
> +
> +enum {
> + ID_FXAS21002C,
> +};
> +
> +enum fxas21002c_operating_mode {
> + FXAS21002C_OM_BOOT,
> + FXAS21002C_OM_STANDBY,
> + FXAS21002C_OM_READY,
> + FXAS21002C_OM_ACTIVE,
> +};
> +
> +struct fxas21002c_data {
> + struct i2c_client *client;
> + struct regmap *regmap;
> +};
> +
> +static const struct regmap_range fxas21002c_writable_ranges[] = {
> + regmap_reg_range(FXAS21002C_REG_F_SETUP, FXAS21002C_REG_F_SETUP),
> + regmap_reg_range(FXAS21002C_REG_CTRL_REG0, FXAS21002C_REG_RT_CFG),
> + regmap_reg_range(FXAS21002C_REG_RT_THS, FXAS21002C_REG_RT_COUNT),
> + regmap_reg_range(FXAS21002C_REG_CTRL_REG1, FXAS21002C_REG_CTRL_REG3),
> +};
> +
> +static const struct regmap_access_table fxas21002c_writable_table = {
> + .yes_ranges = fxas21002c_writable_ranges,
> + .n_yes_ranges = ARRAY_SIZE(fxas21002c_writable_ranges),
> +};
> +
> +static const struct regmap_range fxas21002c_volatile_ranges[] = {
> + regmap_reg_range(FXAS21002C_REG_STATUS, FXAS21002C_REG_F_STATUS),
> + regmap_reg_range(FXAS21002C_REG_F_EVENT, FXAS21002C_REG_INT_SRC_FLAG),
> + regmap_reg_range(FXAS21002C_REG_RT_COUNT, FXAS21002C_REG_CTRL_REG1),
> +};
> +
> +static const struct regmap_access_table fxas21002c_volatile_table = {
> + .yes_ranges = fxas21002c_volatile_ranges,
> + .n_yes_ranges = ARRAY_SIZE(fxas21002c_volatile_ranges),
> +};
> +
> +const struct regmap_config fxas21002c_regmap_config = {
> + .reg_bits = 8,
> + .val_bits = 8,
> +
> + .max_register = FXAS21002C_REG_CTRL_REG3,
> + /* We don't specify a .rd_table because everything is readable */
> + .wr_table = &fxas21002c_writable_table,
> + .volatile_table = &fxas21002c_volatile_table,
> +};
> +
> +#define FXAS21002C_GYRO_CHAN(_axis) { \
> + .type = IIO_ANGL_VEL, \
> + .modified = 1, \
> + .channel2 = IIO_MOD_ ## _axis, \
> + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
> + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
> + BIT(IIO_CHAN_INFO_SAMP_FREQ), \
> + .address = FXAS21002C_REG_OUT_ ## _axis ## _MSB, \
> +}
> +
> +static const struct iio_chan_spec fxas21002c_channels[] = {
> + {
> + .type = IIO_TEMP,
> + .address = FXAS21002C_REG_TEMP,
> + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
> + BIT(IIO_CHAN_INFO_SCALE),
> + },
> + FXAS21002C_GYRO_CHAN(X),
> + FXAS21002C_GYRO_CHAN(Y),
> + FXAS21002C_GYRO_CHAN(Z),
> + IIO_CHAN_SOFT_TIMESTAMP(3),
> +};
> +
> +static int fxas21002c_set_operating_mode(struct fxas21002c_data *data,
> + enum fxas21002c_operating_mode om)
> +{
> + int ret;
> + int mask;
> +
> + switch (om) {
> + case FXAS21002C_OM_STANDBY:
> + mask = 0;
> + break;
> + case FXAS21002C_OM_READY:
> + mask = FXAS21002C_READY_BIT;
> + break;
> + case FXAS21002C_OM_ACTIVE:
> + mask = FXAS21002C_ACTIVE_BIT;
> + break;
> +
> + default:
> + return -EINVAL;
> + }
> +
> + ret = regmap_write(data->regmap, FXAS21002C_REG_CTRL_REG1, mask);
> + if (ret) {
> + dev_err(&data->client->dev,
> + "could not switch operating mode\n");
> + return ret;
> + }
> +
> + msleep(FXAS21002C_MAX_TRANSITION_TIME_MS);
> +
> + return 0;
> +}
> +
> +static void fxas21002c_standby(void *_data)
> +{
> + struct fxas21002c_data *data = _data;
> +
> + fxas21002c_set_operating_mode(data, FXAS21002C_OM_STANDBY);
> +}
> +
> +static int fxas21002c_reset(struct fxas21002c_data *data)
> +{
> + int ret;
> +
> + /*
> + * On issuing a Software Reset command over an I2C interface,
> + * the device immediately resets and does not send any
> + * acknowledgment (ACK) of the written byte to the Master.
> + *
> + * This is documented in table 46 on the datasheet. Due to this
> + * the write will fail with EREMOTEIO.
> + */
> + ret = regmap_write(data->regmap,
> + FXAS21002C_REG_CTRL_REG1, FXAS21002C_RST_BIT);
> +
> + if (ret != -EREMOTEIO) {
> + dev_err(&data->client->dev, "could not reset device\n");
> + return ret;
> + }
> +
> + regcache_mark_dirty(data->regmap);
> +
> + /* Wait for device to boot up */
> + msleep(FXAS21002C_MAX_TRANSITION_TIME_MS);
> +
> + return 0;
> +}
> +
> +static int fxas21002c_verify_chip(struct fxas21002c_data *data)
> +{
> + int ret;
> + unsigned int chip_id;
> +
> + ret = regmap_read(data->regmap, FXAS21002C_REG_WHO_AM_I, &chip_id);
> + if (ret) {
> + dev_err(&data->client->dev, "could not read device id\n");
> + return ret;
> + }
> +
> + if (chip_id != FXAS21002C_CHIP_ID) {
> + dev_err(&data->client->dev,
> + "unsupported chip id %02x\n", chip_id);
> + return -ENODEV;
> + }
> +
> + return 0;
> +}
> +
> +static int fxas21002c_read_oneshot(struct fxas21002c_data *data,
> + struct iio_chan_spec const *chan, int *val)
> +{
> + int ret;
> + __be16 bulk_raw;
> + unsigned int uval;
> +
> + switch (chan->type) {
> + case IIO_ANGL_VEL:
> + ret = regmap_bulk_read(data->regmap, chan->address,
> + &bulk_raw, sizeof(bulk_raw));
> + if (ret)
> + return ret;
> +
> + *val = sign_extend32(be16_to_cpu(bulk_raw), 15);
> + return IIO_VAL_INT;
> + case IIO_TEMP:
> + ret = regmap_read(data->regmap, chan->address, &uval);
> + if (ret)
> + return ret;
> +
> + *val = sign_extend32(uval, 7);
> + return IIO_VAL_INT;
> + default:
> + return -EINVAL;
> + }
> +}
> +
> +static int fxas21002c_read_raw(struct iio_dev *indio_dev,
> + struct iio_chan_spec const *chan, int *val,
> + int *val2, long mask)
> +{
> + struct fxas21002c_data *data = iio_priv(indio_dev);
> +
> + switch (mask) {
> + case IIO_CHAN_INFO_RAW:
> + return fxas21002c_read_oneshot(data, chan, val);
> + case IIO_CHAN_INFO_SCALE:
> + switch (chan->type) {
> + case IIO_ANGL_VEL:
> + *val = 0;
> + *val2 = FXAS21002C_DEFAULT_SENSITIVITY;
> +
> + return IIO_VAL_INT_PLUS_MICRO;
> + case IIO_TEMP:
> + *val = FXAS21002C_TEMP_SCALE;
> +
> + return IIO_VAL_INT;
> + default:
> + return -EINVAL;
> + }
> + case IIO_CHAN_INFO_SAMP_FREQ:
> + if (chan->type != IIO_ANGL_VEL)
> + return -EINVAL;
> +
> + *val = FXAS21002C_DEFAULT_ODR_HZ;
> +
> + return IIO_VAL_INT;
> + }
> +
> + return -EINVAL;
> +}
> +
> +static const struct iio_info fxas21002c_info = {
> + .read_raw = fxas21002c_read_raw,
> +};
> +
> +static int fxas21002c_probe(struct i2c_client *client,
> + const struct i2c_device_id *id)
> +{
> + int ret;
> + struct iio_dev *indio_dev;
> + struct fxas21002c_data *data;
> +
> + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
> + if (!indio_dev)
> + return -ENOMEM;
> +
> + i2c_set_clientdata(client, indio_dev);
> + data = iio_priv(indio_dev);
> + data->client = client;
> +
> + data->regmap = devm_regmap_init_i2c(client, &fxas21002c_regmap_config);
> + if (IS_ERR(data->regmap)) {
> + ret = PTR_ERR(data->regmap);
> + dev_err(&client->dev,
> + "Failed to allocate regmap, err: %d\n", ret);
> + return ret;
> + }
> +
> + indio_dev->dev.parent = &client->dev;
> + indio_dev->channels = fxas21002c_channels;
> + indio_dev->num_channels = ARRAY_SIZE(fxas21002c_channels);
> + indio_dev->name = id->name;
> + indio_dev->modes = INDIO_DIRECT_MODE;
> + indio_dev->info = &fxas21002c_info;
> +
> + ret = fxas21002c_verify_chip(data);
> + if (ret < 0)
> + return ret;
> +
> + ret = fxas21002c_reset(data);
> + if (ret < 0)
> + return ret;
> +
> + ret = fxas21002c_set_operating_mode(data, FXAS21002C_OM_ACTIVE);
> + if (ret < 0)
> + return ret;
> +
> + ret = devm_add_action(&client->dev, fxas21002c_standby, data);
> + if (ret < 0) {
> + fxas21002c_standby(data);
> + dev_err(&client->dev, "failed to add standby action\n");
> + return ret;
> + }
> +
> + ret = iio_device_register(indio_dev);
> + if (ret < 0)
> + dev_err(&client->dev, "failed to register iio device\n");
> +
> + return ret;
> +}
> +
> +static const struct i2c_device_id fxas21002c_id[] = {
> + {"fxas21002c", ID_FXAS21002C},
> + {}
> +};
> +
> +MODULE_DEVICE_TABLE(i2c, fxas21002c_id);
> +
> +static struct i2c_driver fxas21002c_driver = {
> + .driver = {
> + .name = FXAS21002C_DRV_NAME,
> + },
> + .probe = fxas21002c_probe,
> + .id_table = fxas21002c_id,
> +};
> +
> +module_i2c_driver(fxas21002c_driver);
> +
> +MODULE_AUTHOR("Afonso Bordado <[email protected]>");
> +MODULE_DESCRIPTION("FXAS21002C Digital Angular Rate Gyroscope driver");
> +MODULE_LICENSE("GPL v2");
> --
> 2.18.0
>
>


--
With Best Regards,
Andy Shevchenko

2018-09-04 19:27:35

by Andy Shevchenko

[permalink] [raw]
Subject: Re: [PATCH v3 3/4] iio: fxas21002c: add ODR/Scale support

On Tue, Sep 4, 2018 at 10:07 PM Afonso Bordado <[email protected]> wrote:
>
> This patch adds support for reading/writing ODR/Scale
>
> We don't support the scale boost modes.

> @@ -44,7 +44,10 @@
> #define FXAS21002C_REG_F_EVENT 0x0A
> #define FXAS21002C_REG_INT_SRC_FLAG 0x0B
> #define FXAS21002C_REG_WHO_AM_I 0x0C
> +
> #define FXAS21002C_REG_CTRL_REG0 0x0D
> +#define FXAS21002C_SCALE_MASK GENMASK(1, 0)
> +
> #define FXAS21002C_REG_RT_CFG 0x0E
> #define FXAS21002C_REG_RT_SRC 0x0F
> #define FXAS21002C_REG_RT_THS 0x10

This hunk doesn't belong to this patch.

> +static const int fxas21002c_anglevel_scale_avail[4][2] = {
> + [FXAS21002C_SCALE_62MDPS] = { 0, IIO_DEGREE_TO_RAD(62500) },
> + [FXAS21002C_SCALE_31MDPS] = { 0, IIO_DEGREE_TO_RAD(31250) },
> + [FXAS21002C_SCALE_15MDPS] = { 0, IIO_DEGREE_TO_RAD(15625) },
> + [FXAS21002C_SCALE_7MDPS] = { 0, IIO_DEGREE_TO_RAD(7812) },

This is just set of powers of two. No table needed.

> +};

> +static const int fxas21002c_sample_freq_avail[7][2] = {
> + [FXAS21002C_ODR_800] = { 800, 0 },
> + [FXAS21002C_ODR_400] = { 400, 0 },
> + [FXAS21002C_ODR_200] = { 200, 0 },
> + [FXAS21002C_ODR_100] = { 100, 0 },
> + [FXAS21002C_ODR_50] = { 50, 0 },
> + [FXAS21002C_ODR_25] = { 25, 0 },
> + [FXAS21002C_ODR_12_5] = { 12, 500000 },

Ditto.

> +};


--
With Best Regards,
Andy Shevchenko

2018-09-10 20:11:48

by Rob Herring (Arm)

[permalink] [raw]
Subject: Re: [PATCH v3 2/4] iio: gyro: add device tree support for fxas21002c

On Tue, Sep 04, 2018 at 09:04:32PM +0100, Afonso Bordado wrote:
> This patch adds device tree support for the fxas21002c driver, including
> bindings.
>
> Signed-off-by: Afonso Bordado <[email protected]>
> ---
> .../bindings/iio/gyroscope/fsl,fxas21002c.txt | 35 +++++++++++++++++++

Please split bindings to separate patch.

> drivers/iio/gyro/fxas21002c.c | 10 +++++-
> 2 files changed, 44 insertions(+), 1 deletion(-)
> create mode 100644 Documentation/devicetree/bindings/iio/gyroscope/fsl,fxas21002c.txt
>
> diff --git a/Documentation/devicetree/bindings/iio/gyroscope/fsl,fxas21002c.txt b/Documentation/devicetree/bindings/iio/gyroscope/fsl,fxas21002c.txt
> new file mode 100644
> index 000000000000..5f02cfa5ac82
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/iio/gyroscope/fsl,fxas21002c.txt
> @@ -0,0 +1,35 @@
> +* Freescale FXAS21002C Digital Angular Rate Gyroscope
> +
> +Required properties:
> +
> + - compatible: must be "fsl,fxas21002c"
> + - reg : the I2C address of the sensor
> +
> +Optional properties:
> +
> + - interrupt-parent : phandle to the parent interrupt controller.
> + see interrupt-controller/interrupts.txt

This is implied, so drop it.

> + - interrupts : The first interrupt listed must be the one
> + connected to the INT1 pin, the second interrupt
> + listed must be the one connected to the INT2 pin.
> + The interrupts can be triggered on rising or falling
> + edges alike.
> + see interrupt-controller/interrupts.txt
> + - vdd-supply : The main voltage regulator
> + - iovdd-supply : The IO voltage regulator

Some space before tab on these 2 lines.

> + see regulator/regulator.txt
> + - reset-gpios : GPIO used to reset the device.
> + see gpio/gpio.txt.
> + - mount-matrix : see iio/mount-matrix.txt
> +
> +Example:
> +gyroscope@20 {
> + compatible = "fsl,fxas21002c";
> + reg = <0x20>;
> + reset-gpios = <&gpio0 2 0>;
> + vdd-supply = <&vref>;
> + iovdd-supply = <&vref2>;
> + interrupt-parent = <&foo>;
> + interrupts = <0 IRQ_TYPE_EDGE_RISING>,
> + <1 (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)>;
> +};
> diff --git a/drivers/iio/gyro/fxas21002c.c b/drivers/iio/gyro/fxas21002c.c
> index 1668e6f3fe11..18b1f500dd3e 100644
> --- a/drivers/iio/gyro/fxas21002c.c
> +++ b/drivers/iio/gyro/fxas21002c.c
> @@ -8,7 +8,6 @@
> * Datasheet: https://www.nxp.com/docs/en/data-sheet/FXAS21002.pdf
> * TODO:
> * ODR / Scale Support
> - * Devicetree
> * Power management
> * GPIO Reset
> * Power supplies
> @@ -350,6 +349,14 @@ static int fxas21002c_probe(struct i2c_client *client,
> return ret;
> }
>
> +#ifdef CONFIG_OF
> +static const struct of_device_id fxas21002c_of_ids[] = {
> + {.compatible = "fsl,fxas21002c"},
> + {}
> +};
> +MODULE_DEVICE_TABLE(of, fxas21002c_of_ids);
> +#endif
> +
> static const struct i2c_device_id fxas21002c_id[] = {
> {"fxas21002c", ID_FXAS21002C},
> {}
> @@ -360,6 +367,7 @@ MODULE_DEVICE_TABLE(i2c, fxas21002c_id);
> static struct i2c_driver fxas21002c_driver = {
> .driver = {
> .name = FXAS21002C_DRV_NAME,
> + .of_match_table = of_match_ptr(fxas21002c_of_ids),
> },
> .probe = fxas21002c_probe,
> .id_table = fxas21002c_id,
> --
> 2.18.0
>
>