Re: [PATCH v2 3/3] iio: magnetometer: st_magn: honour st,fullscale-milligauss DT property
From: Andy Shevchenko
Date: Wed Jun 17 2026 - 06:10:52 EST
On Tue, Jun 16, 2026 at 03:02:06PM +0200, Herman van Hazendonk wrote:
> The ST magnetometer core's common probe hardcodes fs_avl[0] -- the
> highest-sensitivity full-scale supported by the chip -- as the
> starting range. For the LSM303DLH that is +/-1.3 G; for the
> LSM303DLHC and LSM303DLM it is +/-2 G; for the LIS3MDL it is +/-4 G.
>
> That is the right default for "minimal noise floor at a desk", but
> it leaves no margin for boards that pick up appreciable DC bias from
> nearby PCB structures. On the HP TouchPad (apq8060 / tenderloin) the
> LSM303DLH magnetometer is mounted close enough to the surrounding
> power planes that X reads back as the chip's 0xF000 overflow
> sentinel (== -4096 raw, the value the chip publishes when the ADC
> saturates) on every sample at the chip-default range, while Y and Z
> fall well within the +/-1.3 G window.
>
> Parse the st,fullscale-milligauss device-tree property (documented
> separately in dt-bindings/iio/st,st-sensors.yaml) in the
> magnetometer common probe to select the initial fs_avl entry by its
> mg value. The DT binding pins the accepted value set per compatible
> via allOf/if-then enum clauses, so a malformed mg value fails
> dt_binding_check rather than reaching the driver. Sensors with a
> fixed full-scale (fs.addr == 0: LSM303AGR, LIS2MDL, IIS2MDC) have no
> register to switch and the property is rejected outright for them
> in the binding; the parse block is additionally gated on fs.addr as
> defence in depth against stale DTBs.
>
> Per-sensor mg ranges are listed in st_magn_sensors_settings[]. For
> LSM303DLH and LSM303DLHC/DLM the valid values are 1300, 1900, 2500,
> 4000, 4700, 5600 and 8100; for LIS3MDL, LSM9DS1-magn and LSM303C-magn
> they are 4000, 8000, 12000, 16000.
>
> Empirical scale sweep on the HP TouchPad confirmed that on this
> board any fs_avl >= 1 produces non-saturated X readings:
>
> scale (0.001 G/LSB) | X raw Y raw Z raw
> --------------------+-------------------------------
> 1.100 | -4096 44 46 (X saturated)
> 0.855 | -547 37 37 (clean)
> 0.670 | -433 94 103 (clean)
> 0.450 | -266 44 71 (clean)
> 0.400 | -235 34 65 (clean)
> 0.330 | -196 27 56 (clean)
> 0.230 | -145 15 40 (clean)
>
> 2500 mg is the natural choice for tenderloin: comfortably outside
> the saturation regime while keeping useful precision for compass
> applications.
Not sure if we need that big commit message, better to move to the point.
> + propname = "st,fullscale-milligauss";
> + if (mdata->sensor_settings->fs.addr &&
> + device_property_present(parent, propname)) {
> + struct st_sensor_fullscale *fs = &mdata->sensor_settings->fs;
> + u32 fs_mg;
> + int i;
Instead...
> + err = device_property_read_u32(parent, propname, &fs_mg);
> + if (err)
> + return err;
> + for (i = 0; i < ST_SENSORS_FULLSCALE_AVL_MAX; i++) {
for (unsigned int i = 0; i < ST_SENSORS_FULLSCALE_AVL_MAX; i++) {
> + if (!fs->fs_avl[i].num)
> + break;
> + if (fs->fs_avl[i].num == fs_mg) {
> + mdata->current_fullscale = &fs->fs_avl[i];
> + break;
> + }
> + }
> + if (mdata->current_fullscale->num != fs_mg)
> + dev_warn(parent, "%s=%u not supported, using %u\n",
> + propname, fs_mg,
> + mdata->current_fullscale->num);
> + }
--
With Best Regards,
Andy Shevchenko