From ffe98577544cf36a57e48654e822ade5b25545e8 Mon Sep 17 00:00:00 2001 From: Yiding Jia Date: Mon, 30 Dec 2024 21:12:52 -0800 Subject: [PATCH] drivers: sensor: Fix TMAG5273/TMAG3001 by adding a TMAG3001 compatible Fixes issue introduced in #76460 The previous code attempted to detect whether TMAG5273 or TMAG3001 was connected based on DEVICE ID register. This doesn't work as the bits that denote the version on one part are undefined on the other part, and cannot be relied on to be zero. This commit adds a TMAG3001 compatible which (for now) is just derived from the TMAG5273 compatible. This allows TMAG3001 to be specified directly in the DT. The driver code is updated to support both compatibles. Signed-off-by: Yiding Jia --- drivers/sensor/ti/tmag5273/Kconfig | 2 +- drivers/sensor/ti/tmag5273/tmag5273.c | 93 ++++++++++++++++--------- drivers/sensor/ti/tmag5273/tmag5273.h | 19 ++--- dts/bindings/sensor/ti,tmag3001.yaml | 17 +++++ dts/bindings/sensor/ti,tmag5273.yaml | 1 - tests/drivers/build_all/sensor/i2c.dtsi | 10 +++ 6 files changed, 99 insertions(+), 43 deletions(-) create mode 100644 dts/bindings/sensor/ti,tmag3001.yaml diff --git a/drivers/sensor/ti/tmag5273/Kconfig b/drivers/sensor/ti/tmag5273/Kconfig index 8d45c5d152223..95db0ecc0352e 100644 --- a/drivers/sensor/ti/tmag5273/Kconfig +++ b/drivers/sensor/ti/tmag5273/Kconfig @@ -6,7 +6,7 @@ config TMAG5273 bool "TMAG5273/TMAG3001 3D Hall-Effect Sensor" default y - depends on DT_HAS_TI_TMAG5273_ENABLED + depends on DT_HAS_TI_TMAG5273_ENABLED || DT_HAS_TI_TMAG3001_ENABLED select I2C select GPIO imply CRC diff --git a/drivers/sensor/ti/tmag5273/tmag5273.c b/drivers/sensor/ti/tmag5273/tmag5273.c index 0d53acc269e37..d3711da694420 100644 --- a/drivers/sensor/ti/tmag5273/tmag5273.c +++ b/drivers/sensor/ti/tmag5273/tmag5273.c @@ -4,8 +4,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -#define DT_DRV_COMPAT ti_tmag5273 - #include "tmag5273.h" #include @@ -47,6 +45,11 @@ LOG_MODULE_REGISTER(TMAG5273, CONFIG_SENSOR_LOG_LEVEL); struct tmag5273_config { struct i2c_dt_spec i2c; + enum { + TMAG5273_PART, + TMAG3001_PART + } part; + uint8_t mag_channel; uint8_t axis; bool temperature; @@ -71,8 +74,8 @@ struct tmag5273_config { }; struct tmag5273_data { - uint8_t version; /** version as given by the sensor */ - uint16_t conversion_time_us; /** time for one conversion */ + enum tmag5273_version version; /** version as given by the sensor */ + uint16_t conversion_time_us; /** time for one conversion */ int16_t x_sample; /** measured B-field @x-axis */ int16_t y_sample; /** measured B-field @y-axis */ @@ -1152,7 +1155,26 @@ static int tmag5273_init(const struct device *dev) return -EIO; } - drv_data->version = regdata & TMAG5273_VER_MSK; + switch (drv_cfg->part) { + case TMAG5273_PART: + drv_data->version = regdata & TMAG5273_VER_MSK; + break; + case TMAG3001_PART: + drv_data->version = regdata & TMAG3001_VER_MSK; + break; + default: + __ASSERT(false, "invalid part %d", drv_cfg->part); + } + switch (drv_data->version) { + case TMAG5273_VER_TMAG5273X1: + case TMAG5273_VER_TMAG5273X2: + case TMAG5273_VER_TMAG3001X1: + case TMAG5273_VER_TMAG3001X2: + break; + default: + LOG_ERR("unsupported version %d", drv_data->version); + return -EIO; + } /* magnetic measurement range based on version, apply correct one */ if (drv_cfg->meas_range == TMAG5273_DT_AXIS_RANGE_LOW) { @@ -1217,33 +1239,38 @@ static DEVICE_API(sensor, tmag5273_driver_api) = { : 0) /** Instantiation macro */ -#define TMAG5273_DEFINE(inst) \ - BUILD_ASSERT(IS_ENABLED(CONFIG_CRC) || (DT_INST_PROP(inst, crc_enabled) == 0), \ +#define TMAG5273_DEFINE(inst, compat, _part) \ + BUILD_ASSERT(IS_ENABLED(CONFIG_CRC) || (DT_PROP(DT_INST(inst, compat), crc_enabled) == 0), \ "CRC support necessary"); \ - BUILD_ASSERT(!DT_INST_PROP(inst, trigger_conversion_via_int) || \ - DT_INST_NODE_HAS_PROP(inst, int_gpios), \ + BUILD_ASSERT(!DT_PROP(DT_INST(inst, compat), trigger_conversion_via_int) || \ + DT_NODE_HAS_PROP(DT_INST(inst, compat), int_gpios), \ "trigger-conversion-via-int requires int-gpios to be defined"); \ - static const struct tmag5273_config tmag5273_driver_cfg##inst = { \ - .i2c = I2C_DT_SPEC_INST_GET(inst), \ - .mag_channel = DT_INST_PROP(inst, axis), \ - .axis = (TMAG5273_DT_X_AXIS_BIT(DT_INST_PROP(inst, axis)) | \ - TMAG5273_DT_Y_AXIS_BIT(DT_INST_PROP(inst, axis)) | \ - TMAG5273_DT_Z_AXIS_BIT(DT_INST_PROP(inst, axis))), \ - .temperature = DT_INST_PROP(inst, temperature), \ - .meas_range = DT_INST_PROP(inst, range), \ - .temperature_coefficient = DT_INST_PROP(inst, temperature_coefficient), \ - .angle_magnitude_axis = DT_INST_PROP(inst, angle_magnitude_axis), \ - .ch_mag_gain_correction = DT_INST_PROP(inst, ch_mag_gain_correction), \ - .operation_mode = DT_INST_PROP(inst, operation_mode), \ - .averaging = DT_INST_PROP(inst, average_mode), \ - .trigger_conv_via_int = DT_INST_PROP(inst, trigger_conversion_via_int), \ - .low_noise_mode = DT_INST_PROP(inst, low_noise), \ - .ignore_diag_fail = DT_INST_PROP(inst, ignore_diag_fail), \ - .int_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, int_gpios, {0}), \ - IF_ENABLED(CONFIG_CRC, (.crc_enabled = DT_INST_PROP(inst, crc_enabled),))}; \ - static struct tmag5273_data tmag5273_driver_data##inst; \ - SENSOR_DEVICE_DT_INST_DEFINE(inst, tmag5273_init, NULL, &tmag5273_driver_data##inst, \ - &tmag5273_driver_cfg##inst, POST_KERNEL, \ - CONFIG_SENSOR_INIT_PRIORITY, &tmag5273_driver_api); - -DT_INST_FOREACH_STATUS_OKAY(TMAG5273_DEFINE) + static const struct tmag5273_config compat##_driver_cfg##inst = { \ + .i2c = I2C_DT_SPEC_GET(DT_INST(inst, compat)), \ + .part = _part, \ + .mag_channel = DT_PROP(DT_INST(inst, compat), axis), \ + .axis = (TMAG5273_DT_X_AXIS_BIT(DT_PROP(DT_INST(inst, compat), axis)) | \ + TMAG5273_DT_Y_AXIS_BIT(DT_PROP(DT_INST(inst, compat), axis)) | \ + TMAG5273_DT_Z_AXIS_BIT(DT_PROP(DT_INST(inst, compat), axis))), \ + .temperature = DT_PROP(DT_INST(inst, compat), temperature), \ + .meas_range = DT_PROP(DT_INST(inst, compat), range), \ + .temperature_coefficient = \ + DT_PROP(DT_INST(inst, compat), temperature_coefficient), \ + .angle_magnitude_axis = DT_PROP(DT_INST(inst, compat), angle_magnitude_axis), \ + .ch_mag_gain_correction = DT_PROP(DT_INST(inst, compat), ch_mag_gain_correction), \ + .operation_mode = DT_PROP(DT_INST(inst, compat), operation_mode), \ + .averaging = DT_PROP(DT_INST(inst, compat), average_mode), \ + .trigger_conv_via_int = \ + DT_PROP(DT_INST(inst, compat), trigger_conversion_via_int), \ + .low_noise_mode = DT_PROP(DT_INST(inst, compat), low_noise), \ + .ignore_diag_fail = DT_PROP(DT_INST(inst, compat), ignore_diag_fail), \ + .int_gpio = GPIO_DT_SPEC_GET_OR(DT_INST(inst, compat), int_gpios, {0}), \ + IF_ENABLED(CONFIG_CRC, \ + (.crc_enabled = DT_PROP(DT_INST(inst, compat), crc_enabled),))}; \ + static struct tmag5273_data compat##_driver_data##inst; \ + SENSOR_DEVICE_DT_DEFINE(DT_INST(inst, compat), tmag5273_init, NULL, \ + &compat##_driver_data##inst, &compat##_driver_cfg##inst, \ + POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, &tmag5273_driver_api); + +DT_COMPAT_FOREACH_STATUS_OKAY_VARGS(ti_tmag5273, TMAG5273_DEFINE, TMAG5273_PART) +DT_COMPAT_FOREACH_STATUS_OKAY_VARGS(ti_tmag3001, TMAG5273_DEFINE, TMAG3001_PART) diff --git a/drivers/sensor/ti/tmag5273/tmag5273.h b/drivers/sensor/ti/tmag5273/tmag5273.h index 76cc84a99ab8c..461e311ea46af 100644 --- a/drivers/sensor/ti/tmag5273/tmag5273.h +++ b/drivers/sensor/ti/tmag5273/tmag5273.h @@ -194,14 +194,17 @@ #define TMAG5273_I2C_ADDRESS_UPDATE_ENABLE (1 << TMAG5273_I2C_ADDRESS_UPDATE_EN_POS) /* Register DEVICE_ID */ -#define TMAG5273_VER_POS 0 -#define TMAG3001_VER_POS 2 -#define TMAG5273_VER_MSK GENMASK(3, 0) - -#define TMAG5273_VER_TMAG5273X1 (1 << TMAG5273_VER_POS) -#define TMAG5273_VER_TMAG5273X2 (2 << TMAG5273_VER_POS) -#define TMAG5273_VER_TMAG3001X1 (0 << TMAG3001_VER_POS) -#define TMAG5273_VER_TMAG3001X2 (2 << TMAG3001_VER_POS) +#define TMAG5273_VER_POS 0 +#define TMAG3001_VER_POS 2 +#define TMAG5273_VER_MSK GENMASK(1, 0) +#define TMAG3001_VER_MSK GENMASK(3, 2) + +enum tmag5273_version { + TMAG5273_VER_TMAG5273X1 = 1 << TMAG5273_VER_POS, + TMAG5273_VER_TMAG5273X2 = 2 << TMAG5273_VER_POS, + TMAG5273_VER_TMAG3001X1 = 0 << TMAG3001_VER_POS, + TMAG5273_VER_TMAG3001X2 = 2 << TMAG3001_VER_POS, +}; /* Register CONV_STATUS */ #define TMAG5273_SET_COUNT_POS 5 diff --git a/dts/bindings/sensor/ti,tmag3001.yaml b/dts/bindings/sensor/ti,tmag3001.yaml new file mode 100644 index 0000000000000..0d0588662fb58 --- /dev/null +++ b/dts/bindings/sensor/ti,tmag3001.yaml @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: Apache-2.0 +description: | + TMAG3001 Low-Power 3D Linear and Angle Hall-Effect Sensor With I2C Interface + and Wake Up Detection in WCSP. + + See the specification for the default I2C address. + + The specification of the sensor can be found at: + https://www.ti.com/lit/ds/symlink/tmag3001.pdf + + Currently, this driver shares implementation with tmag5273. When setting the + enum properties in a .dts or .dtsi file you may include + `zephyr/dt-bindings/sensor/tmag5273.h` and use the macros defined there. + +compatible: "ti,tmag3001" + +include: ["ti,tmag5273.yaml"] diff --git a/dts/bindings/sensor/ti,tmag5273.yaml b/dts/bindings/sensor/ti,tmag5273.yaml index afe9576291073..76f5eefe8d0b8 100644 --- a/dts/bindings/sensor/ti,tmag5273.yaml +++ b/dts/bindings/sensor/ti,tmag5273.yaml @@ -8,7 +8,6 @@ description: | The specification of the sensor can be found at: https://www.ti.com/lit/ds/symlink/tmag5273.pdf - https://www.ti.com/lit/ds/symlink/tmag3001.pdf When setting the enum properties in a .dts or .dtsi file you may include tmag5273.h and use the macros defined there. diff --git a/tests/drivers/build_all/sensor/i2c.dtsi b/tests/drivers/build_all/sensor/i2c.dtsi index 2f8b412b36658..9a84104e1eddf 100644 --- a/tests/drivers/build_all/sensor/i2c.dtsi +++ b/tests/drivers/build_all/sensor/i2c.dtsi @@ -1201,3 +1201,13 @@ test_i2c_lis2duxs12: lis2duxs12@a7 { power-mode = ; status = "okay"; }; + +test_i2c_tmag3001: tmag3001@a8 { + compatible = "ti,tmag3001"; + status = "okay"; + reg = <0xa8>; + int-gpios = <&test_gpio 15 1>; + + operation-mode = ; + angle-magnitude-axis = ; +};