From patchwork Sun Jul 10 09:14:55 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angel Iglesias X-Patchwork-Id: 12912490 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 25D79CCA479 for ; Sun, 10 Jul 2022 09:15:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229523AbiGJJPK (ORCPT ); Sun, 10 Jul 2022 05:15:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40152 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229476AbiGJJPK (ORCPT ); Sun, 10 Jul 2022 05:15:10 -0400 Received: from mail-wm1-x32d.google.com (mail-wm1-x32d.google.com [IPv6:2a00:1450:4864:20::32d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D02BDE0C8; Sun, 10 Jul 2022 02:15:08 -0700 (PDT) Received: by mail-wm1-x32d.google.com with SMTP id 9-20020a1c0209000000b003a2dfdebe47so620750wmc.3; Sun, 10 Jul 2022 02:15:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=Vc7tw6mjJ5Kc17Ui5i1QizKqiPx9CvjzA49Ha2NV+Nw=; b=Ty/2rr5vN64Q6JitKGJrkeJIksYnyifTseF1jGfltq3HtT9zSawk0G4qteU1pYLrvP P2/CDwrl2XPxJpb6eVR/LMYRlE96h+Gc1mHB77nHF2XGBIb0BE6XiELjEgjN/faIIFqL wekBIg+aVusJZ7vBY4lsdYKvFDc6BK1BuvIUGR/EHK+u9u0PXb8oJsXBuRsuMJlnwilA VFrptUc7raP/8PCbJ+/p084yMBAf+V4xTbzbSVTakFRTMXgxG7KjxKSMCCDzBqv+e04S PGVs0v6kNVhNDsY2WWkGqMyhgFSjwt6MZZYa9z8JaySrUX5CtBqOp6CaS78iU897U+Cx s1Bw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=Vc7tw6mjJ5Kc17Ui5i1QizKqiPx9CvjzA49Ha2NV+Nw=; b=C3pnwSfHRJFzxdYYNu6nhPYxm3V3QmbvGetWeTfti+s2yUljuasXynz07Y07ejBFb0 eNdKf9tND/GaiCqp9EKaSMxQ/N+ScMJo9lOt4DHV1UGHWTmbzzMFfJToGHB+KUdRGL9f DxlUTl1yaUMw7aoTN4r6ItwQ6r5Mx4G+PLuC8AJMjkF/iEoEwQ3pq/XDs0Iz34xMZO0s +DFt0TUMHML0CC/Z+8ziKQTTq9blx6wuAkUFntPmRv1UFhhsmssuDhRkL40cJ6MnEF54 L0/WRNuZ4P5eSlhZfJ1w5dSLxp0V+sSWE5KaB24PU/+0v8ISS+PFOM7eRv4T2tgdgm5m J09g== X-Gm-Message-State: AJIora85TxG5AKLKvkQwx2uw6lWmTuO4cifXsTqId44tsF+O2rK57UPl algAiCXedf1Qc5AWm9NQRxRVdplPVb8= X-Google-Smtp-Source: AGRyM1u9/6oh+NaijHI/FNEYiao0fJn8a5ZlJyOi2B/MDBvs+WLaMw3F529PrCZz/fCp9vjWg42TyA== X-Received: by 2002:a05:600c:5108:b0:3a1:a0c2:ba47 with SMTP id o8-20020a05600c510800b003a1a0c2ba47mr10214381wms.68.1657444507135; Sun, 10 Jul 2022 02:15:07 -0700 (PDT) Received: from xps-work.lan (214.red-83-37-4.dynamicip.rima-tde.net. [83.37.4.214]) by smtp.gmail.com with ESMTPSA id n8-20020a7bc5c8000000b0039c457cea21sm3475469wmk.34.2022.07.10.02.15.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 Jul 2022 02:15:06 -0700 (PDT) From: Angel Iglesias To: linux-iio@vger.kernel.org Cc: Angel Iglesias , Krzysztof Kozlowski , Jonathan Cameron , Lars-Peter Clausen , Rob Herring , Krzysztof Kozlowski , Andreas Klinger , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 1/5] dt-bindings: iio: pressure: bmp085: Add BMP380 compatible string Date: Sun, 10 Jul 2022 11:14:55 +0200 Message-Id: <20220710091456.15789-1-ang.iglesiasg@gmail.com> X-Mailer: git-send-email 2.36.1 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Add bosch,bmp380 compatible string for the new family of sensors. This family includes the BMP380, BMP384 and BMP388. The register map in this family changes substantially and introduces new features but core concepts and operations carryover from the previous iterations Signed-off-by: Angel Iglesias Acked-by: Krzysztof Kozlowski --- Documentation/devicetree/bindings/iio/pressure/bmp085.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/iio/pressure/bmp085.yaml b/Documentation/devicetree/bindings/iio/pressure/bmp085.yaml index 49257f9251e8..72cd2c2d3f17 100644 --- a/Documentation/devicetree/bindings/iio/pressure/bmp085.yaml +++ b/Documentation/devicetree/bindings/iio/pressure/bmp085.yaml @@ -4,7 +4,7 @@ $id: http://devicetree.org/schemas/iio/pressure/bmp085.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: BMP085/BMP180/BMP280/BME280 pressure iio sensors +title: BMP085/BMP180/BMP280/BME280/BMP380 pressure iio sensors maintainers: - Andreas Klinger @@ -16,6 +16,7 @@ description: | https://www.bosch-sensortec.com/bst/products/all_products/bmp180 https://www.bosch-sensortec.com/bst/products/all_products/bmp280 https://www.bosch-sensortec.com/bst/products/all_products/bme280 + https://www.bosch-sensortec.com/bst/products/all_products/bmp380 properties: compatible: @@ -24,6 +25,7 @@ properties: - bosch,bmp180 - bosch,bmp280 - bosch,bme280 + - bosch,bmp380 reg: maxItems: 1 From patchwork Sun Jul 10 09:16:17 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angel Iglesias X-Patchwork-Id: 12912491 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7B4ADC43334 for ; Sun, 10 Jul 2022 09:16:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229482AbiGJJQa (ORCPT ); Sun, 10 Jul 2022 05:16:30 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40880 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229476AbiGJJQa (ORCPT ); Sun, 10 Jul 2022 05:16:30 -0400 Received: from mail-wm1-x32c.google.com (mail-wm1-x32c.google.com [IPv6:2a00:1450:4864:20::32c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4F6481116F; Sun, 10 Jul 2022 02:16:29 -0700 (PDT) Received: by mail-wm1-x32c.google.com with SMTP id v67-20020a1cac46000000b003a1888b9d36so3432276wme.0; Sun, 10 Jul 2022 02:16:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=Wk03GQ0nSPYqIEk1dZzt6VvmKU7y/8252uMqRAR8CRY=; b=lnOa2OrmGZXQoo4U96oCF3147qcSMQyzUZhuTR8ZTHgk0sCyP59mV6M7nwyXb4coD8 oC0QMh0e252gQZr06eCRQ5cykUep4JYZjKQMQKVq5G6XUbJYa4Z8tIAWQouWaySTERGc qnM+QiTGwsI/Y159nE967HjbT8jiBA/x/kXzyTnilsL4tCiLbN3uuzZS1UxkQVKh4CW1 fjMwpOD4c+L4u9Y3vgkroC1u2f1igPa+1zmJEkw6JBv6BM5QgUVaqsr6x2UmcPXvSd5x SuJagatcOV/pM0zK6EEMO1v+QqGU35PFRF1Wy6jaDjS2QN9+cClBLBtxb+7NppeTslCi Y3OQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=Wk03GQ0nSPYqIEk1dZzt6VvmKU7y/8252uMqRAR8CRY=; b=H8tjD1jbDN3Kmtv51iFV8DD3fGxD+/KTIlHNsHT+98F8/lMfga3gYzRWntZecj637S sES7ukoxRynXkoXdEtghPITPO4dtD+I8VR3Yl4F/1B7wAwZmqoSvwG4yn8HfYcNHgKT1 lONu/ZWM23k/WXACAtIY5NsF8ng4MIipH9QgacVGYnIt/6znWkTRsN70FEgNbJ+oOAbb UIWh22Z4VMzLRC3lX8xCZoI7gSm7yZDfp2raR9Nd+qOOVRFEzi5jZbFNKJTgtGIseX0o Qv9z/UCNzrD5bGOwZe82Wdul5ysY9KxlSH7WjuQ/C/wybdAwXPpsJm0LXT98r8Vh1znv FWAA== X-Gm-Message-State: AJIora8Crp0e86wrdupw6XBxW9XuCFMs3TJ7vNeyzPYlSX37eCxBgX5+ ybEgzAGVY5dcJYblFJedKDQ= X-Google-Smtp-Source: AGRyM1sjw0koCCA2LlABsjzsANrayWgZ6Q8pHskW/7mzOeFTnHWWKu38ONlz86dhve/zO6DsHYG7Nw== X-Received: by 2002:a05:600c:4f03:b0:3a0:55a2:bb4 with SMTP id l3-20020a05600c4f0300b003a055a20bb4mr9402455wmq.181.1657444587982; Sun, 10 Jul 2022 02:16:27 -0700 (PDT) Received: from xps-work.lan (214.red-83-37-4.dynamicip.rima-tde.net. [83.37.4.214]) by smtp.gmail.com with ESMTPSA id i2-20020adfdec2000000b0021d76985929sm3143569wrn.80.2022.07.10.02.16.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 Jul 2022 02:16:27 -0700 (PDT) From: Angel Iglesias To: Andy Shevchenko Cc: Angel Iglesias , Jonathan Cameron , Lars-Peter Clausen , Nikita Yushchenko , linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 2/5] iio: pressure: Kconfig: Add references to BMP380 Date: Sun, 10 Jul 2022 11:16:17 +0200 Message-Id: <20220710091618.15890-1-ang.iglesiasg@gmail.com> X-Mailer: git-send-email 2.36.1 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Adds reference to BMP380 in bmp280 driver descriptions and symbols Signed-off-by: Angel Iglesias --- drivers/iio/pressure/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig index 0ff756cea63a..c9453389e4f7 100644 --- a/drivers/iio/pressure/Kconfig +++ b/drivers/iio/pressure/Kconfig @@ -17,14 +17,14 @@ config ABP060MG will be called abp060mg. config BMP280 - tristate "Bosch Sensortec BMP180/BMP280 pressure sensor I2C driver" + tristate "Bosch Sensortec BMP180/BMP280/BMP380 pressure sensor I2C driver" depends on (I2C || SPI_MASTER) select REGMAP select BMP280_I2C if (I2C) select BMP280_SPI if (SPI_MASTER) help - Say yes here to build support for Bosch Sensortec BMP180 and BMP280 - pressure and temperature sensors. Also supports the BME280 with + Say yes here to build support for Bosch Sensortec BMP180, BMP280 and + BMP380 pressure and temperature sensors. Also supports the BME280 with an additional humidity sensor channel. To compile this driver as a module, choose M here: the core module From patchwork Sun Jul 10 09:17:06 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angel Iglesias X-Patchwork-Id: 12912492 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 04E64C43334 for ; Sun, 10 Jul 2022 09:17:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229505AbiGJJRS (ORCPT ); Sun, 10 Jul 2022 05:17:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41298 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229476AbiGJJRS (ORCPT ); Sun, 10 Jul 2022 05:17:18 -0400 Received: from mail-wm1-x335.google.com (mail-wm1-x335.google.com [IPv6:2a00:1450:4864:20::335]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 12E7A1116F; Sun, 10 Jul 2022 02:17:16 -0700 (PDT) Received: by mail-wm1-x335.google.com with SMTP id bi22-20020a05600c3d9600b003a04de22ab6so1470260wmb.1; Sun, 10 Jul 2022 02:17:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=2h7tebNzxBgXWYha2s0151QeZmHD5NF+qkk3vM1IJVM=; b=UjBwaLT1eJEfYenGXG+jPFEZi7AQfBXIhcHDykRC1/yAS8+kR0MMXkXKmcO5rWNAg8 cd3SmgvUh9h97V7i4qHmsI0eA2yRxhTHcnVZurzUFPTvn4isDyUydFKkrcpOk9DMn3QV c4B3/eQvCd9KECVXtahwUprKeVF5JSxs/kiH/GEKeeXinMeG3Ew4rPJc0966aiQzRAFY DijPkh6Ad6A4zqXRKqY3RzxkanWopnZdAO261qdQ1AQXcLS2WNUt+TDkNbHT+nCKc3Xv Y6AfEEGtRAvsi3OKiKuLB+mDYeA863TIK8plMv8xyrDrrH4i68CuFfbeJMNi4Afs0jnG Uxsw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=2h7tebNzxBgXWYha2s0151QeZmHD5NF+qkk3vM1IJVM=; b=VHgXue6X9plrFOAyymBH9kKOi8eUSGy0OCDsWHUgPnweqJvPwaUTPs0ZaJ8JbUQKcp u6n3Aj9Z40cpOzjeM2qUYfYed9gEqShH7xSKgPSPJ9M1mlqQaO+7EGDqXNo4c2+Wj7f0 uYkrcOiROU4jMQBghW+9/zgflJOB58ATsze4GF6vPof1eyOxeclz7qE1InuxCWHPbfoh I7Zvr1/sjui13oJii4GxJ11vNBLQ/rigX9Rv22i5dXUYsxvnlvpqsfHI4RaO987IuDMJ S1WuvZ6GhiFUyeduYFxQbk809enH81a+PcERpDdvc+Y5HD6c7imQdOd7fQobye36Cvl5 TNzw== X-Gm-Message-State: AJIora9xfDX9O6NIBd7Lc+KEShowRLZJ0t3wznI60hYL0CWDMRzR9oR2 P/EcfY4eWWUwDDeJHW8HPQQ= X-Google-Smtp-Source: AGRyM1sfvGkk7u/6S+9EV0cDEN2kU1r/y2jt52RdPS39XmE0EYM9pAd36tHqdG+b1BLRr5qto/vSqQ== X-Received: by 2002:a05:600c:4e0f:b0:3a2:e60a:d953 with SMTP id b15-20020a05600c4e0f00b003a2e60ad953mr948803wmq.96.1657444634535; Sun, 10 Jul 2022 02:17:14 -0700 (PDT) Received: from xps-work.lan (214.red-83-37-4.dynamicip.rima-tde.net. [83.37.4.214]) by smtp.gmail.com with ESMTPSA id c3-20020a5d63c3000000b002167efdd549sm3194010wrw.38.2022.07.10.02.17.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 Jul 2022 02:17:14 -0700 (PDT) From: Angel Iglesias To: Andy Shevchenko Cc: Angel Iglesias , Jonathan Cameron , Lars-Peter Clausen , Ulf Hansson , Paul Cercueil , "Rafael J. Wysocki" , linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 3/5] iio: pressure: bmp280: simplify driver initialization logic Date: Sun, 10 Jul 2022 11:17:06 +0200 Message-Id: <20220710091708.15967-1-ang.iglesiasg@gmail.com> X-Mailer: git-send-email 2.36.1 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Simplified common initialization logic of different sensor types unifying calibration and initial configuration recovery. Default config param values of each sensor type are stored inside chip_info structure and used to initialize sensor data struct instance. The auxiliar functions for read each sensor type calibration are converted to a callback available on the chip_info struct. Signed-off-by: Angel Iglesias Suggested-by: Jonathan Cameron --- drivers/iio/pressure/bmp280-core.c | 91 ++++++++++++++++++------------ 1 file changed, 54 insertions(+), 37 deletions(-) diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c index bf8167f43c56..59e9c5fb4ab4 100644 --- a/drivers/iio/pressure/bmp280-core.c +++ b/drivers/iio/pressure/bmp280-core.c @@ -107,19 +107,28 @@ struct bmp280_data { }; struct bmp280_chip_info { + unsigned int id_reg; + + int num_channels; + unsigned int start_up_time; + const int *oversampling_temp_avail; int num_oversampling_temp_avail; + int oversampling_temp_default; const int *oversampling_press_avail; int num_oversampling_press_avail; + int oversampling_press_default; const int *oversampling_humid_avail; int num_oversampling_humid_avail; + int oversampling_humid_default; int (*chip_config)(struct bmp280_data *); int (*read_temp)(struct bmp280_data *, int *); int (*read_press)(struct bmp280_data *, int *, int *); int (*read_humid)(struct bmp280_data *, int *, int *); + int (*read_calib)(struct bmp280_data *, unsigned int); }; /* @@ -147,15 +156,14 @@ static const struct iio_chan_spec bmp280_channels[] = { }, }; -static int bmp280_read_calib(struct bmp280_data *data, - struct bmp280_calib *calib, - unsigned int chip) +static int bmp280_read_calib(struct bmp280_data *data, unsigned int chip) { int ret; unsigned int tmp; __le16 l16; __be16 b16; struct device *dev = data->dev; + struct bmp280_calib *calib = &data->calib.bmp280; __le16 t_buf[BMP280_COMP_TEMP_REG_COUNT / 2]; __le16 p_buf[BMP280_COMP_PRESS_REG_COUNT / 2]; @@ -640,15 +648,22 @@ static int bmp280_chip_config(struct bmp280_data *data) static const int bmp280_oversampling_avail[] = { 1, 2, 4, 8, 16 }; static const struct bmp280_chip_info bmp280_chip_info = { + .id_reg = BMP280_REG_ID, + .start_up_time = 2000, + .num_channels = 2, + .oversampling_temp_avail = bmp280_oversampling_avail, .num_oversampling_temp_avail = ARRAY_SIZE(bmp280_oversampling_avail), + .oversampling_temp_default = ilog2(2), .oversampling_press_avail = bmp280_oversampling_avail, .num_oversampling_press_avail = ARRAY_SIZE(bmp280_oversampling_avail), + .oversampling_press_default = ilog2(16), .chip_config = bmp280_chip_config, .read_temp = bmp280_read_temp, .read_press = bmp280_read_press, + .read_calib = bmp280_read_calib, }; static int bme280_chip_config(struct bmp280_data *data) @@ -670,19 +685,27 @@ static int bme280_chip_config(struct bmp280_data *data) } static const struct bmp280_chip_info bme280_chip_info = { + .id_reg = BMP280_REG_ID, + .start_up_time = 2000, + .num_channels = 3, + .oversampling_temp_avail = bmp280_oversampling_avail, .num_oversampling_temp_avail = ARRAY_SIZE(bmp280_oversampling_avail), + .oversampling_temp_default = ilog2(2), .oversampling_press_avail = bmp280_oversampling_avail, .num_oversampling_press_avail = ARRAY_SIZE(bmp280_oversampling_avail), + .oversampling_press_default = ilog2(16), .oversampling_humid_avail = bmp280_oversampling_avail, .num_oversampling_humid_avail = ARRAY_SIZE(bmp280_oversampling_avail), + .oversampling_humid_default = ilog2(16), .chip_config = bme280_chip_config, .read_temp = bmp280_read_temp, .read_press = bmp280_read_press, .read_humid = bmp280_read_humid, + .read_calib = bmp280_read_calib, }; static int bmp180_measure(struct bmp280_data *data, u8 ctrl_meas) @@ -748,11 +771,11 @@ static int bmp180_read_adc_temp(struct bmp280_data *data, int *val) return 0; } -static int bmp180_read_calib(struct bmp280_data *data, - struct bmp180_calib *calib) +static int bmp180_read_calib(struct bmp280_data *data, unsigned int chip) { int ret; int i; + struct bmp180_calib *calib = &data->calib.bmp180; __be16 buf[BMP180_REG_CALIB_COUNT / 2]; ret = regmap_bulk_read(data->regmap, BMP180_REG_CALIB_START, buf, @@ -913,17 +936,24 @@ static const int bmp180_oversampling_temp_avail[] = { 1 }; static const int bmp180_oversampling_press_avail[] = { 1, 2, 4, 8 }; static const struct bmp280_chip_info bmp180_chip_info = { + .id_reg = BMP280_REG_ID, + .start_up_time = 2000, + .num_channels = 2, + .oversampling_temp_avail = bmp180_oversampling_temp_avail, .num_oversampling_temp_avail = ARRAY_SIZE(bmp180_oversampling_temp_avail), + .oversampling_temp_default = ilog2(1), .oversampling_press_avail = bmp180_oversampling_press_avail, .num_oversampling_press_avail = ARRAY_SIZE(bmp180_oversampling_press_avail), + .oversampling_press_default = ilog2(8), .chip_config = bmp180_chip_config, .read_temp = bmp180_read_temp, .read_press = bmp180_read_press, + .read_calib = bmp180_read_calib, }; static irqreturn_t bmp085_eoc_irq(int irq, void *d) @@ -993,6 +1023,7 @@ int bmp280_common_probe(struct device *dev, int ret; struct iio_dev *indio_dev; struct bmp280_data *data; + const struct bmp280_chip_info *chip_info; unsigned int chip_id; struct gpio_desc *gpiod; @@ -1011,30 +1042,25 @@ int bmp280_common_probe(struct device *dev, switch (chip) { case BMP180_CHIP_ID: - indio_dev->num_channels = 2; - data->chip_info = &bmp180_chip_info; - data->oversampling_press = ilog2(8); - data->oversampling_temp = ilog2(1); - data->start_up_time = 10000; + chip_info = &bmp180_chip_info; break; case BMP280_CHIP_ID: - indio_dev->num_channels = 2; - data->chip_info = &bmp280_chip_info; - data->oversampling_press = ilog2(16); - data->oversampling_temp = ilog2(2); - data->start_up_time = 2000; + chip_info = &bmp280_chip_info; break; case BME280_CHIP_ID: - indio_dev->num_channels = 3; - data->chip_info = &bme280_chip_info; - data->oversampling_press = ilog2(16); - data->oversampling_humid = ilog2(16); - data->oversampling_temp = ilog2(2); - data->start_up_time = 2000; + chip_info = &bme280_chip_info; break; default: return -EINVAL; } + data->chip_info = chip_info; + + /* apply initial values from chip info structure */ + indio_dev->num_channels = chip_info->num_channels; + data->oversampling_press = chip_info->oversampling_press_default; + data->oversampling_humid = chip_info->oversampling_humid_default; + data->oversampling_temp = chip_info->oversampling_temp_default; + data->start_up_time = chip_info->start_up_time; /* Bring up regulators */ regulator_bulk_set_supply_names(data->supplies, @@ -1071,7 +1097,8 @@ int bmp280_common_probe(struct device *dev, } data->regmap = regmap; - ret = regmap_read(regmap, BMP280_REG_ID, &chip_id); + + ret = regmap_read(regmap, data->chip_info->id_reg, &chip_id); if (ret < 0) return ret; if (chip_id != chip) { @@ -1091,21 +1118,11 @@ int bmp280_common_probe(struct device *dev, * non-volatile memory during production". Let's read them out at probe * time once. They will not change. */ - if (chip_id == BMP180_CHIP_ID) { - ret = bmp180_read_calib(data, &data->calib.bmp180); - if (ret < 0) { - dev_err(data->dev, - "failed to read calibration coefficients\n"); - return ret; - } - } else if (chip_id == BMP280_CHIP_ID || chip_id == BME280_CHIP_ID) { - ret = bmp280_read_calib(data, &data->calib.bmp280, chip_id); - if (ret < 0) { - dev_err(data->dev, - "failed to read calibration coefficients\n"); - return ret; - } - } + + ret = data->chip_info->read_calib(data, chip_id); + if (ret < 0) + return dev_err_probe(data->dev, ret, + "failed to read calibration coefficients\n"); /* * Attempt to grab an optional EOC IRQ - only the BMP085 has this From patchwork Sun Jul 10 09:18:31 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angel Iglesias X-Patchwork-Id: 12912493 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 38678C43334 for ; Sun, 10 Jul 2022 09:19:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229476AbiGJJTB (ORCPT ); Sun, 10 Jul 2022 05:19:01 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42978 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229469AbiGJJTA (ORCPT ); Sun, 10 Jul 2022 05:19:00 -0400 Received: from mail-wr1-x430.google.com (mail-wr1-x430.google.com [IPv6:2a00:1450:4864:20::430]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E8D7EB7E; Sun, 10 Jul 2022 02:18:57 -0700 (PDT) Received: by mail-wr1-x430.google.com with SMTP id z12so3514934wrq.7; Sun, 10 Jul 2022 02:18:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=FTUIQLG67q4L37zxmd4J6MTyL080A6Y33cHJDWComPQ=; b=l2bBD4BBuPz2950wQ1xfadfC4sTwSA7FbX+DnL7TNwCoSjzJoHb9IXSdRZYOfcBJGj zwh3b+b9oq14VKoBQNMWuraVKAbA5UIhmme6/GopYVfgZ8Ze38BeCGd80RaUvkmYm3pF oMvhDF2cMqBqMHB9L87kR2Gwe0Yj/ZUqQX8wiMR80bJziETPbm53dPBjyrSkJUwHTE1B M78+jqPpeQM5b7yg5PmEvMgbYhdP4Hf+HOqpri9BhhwbTlxDOI+QKZYP+ONPVWPhM/zz Xhcbw3q1U1X5t72bgcFoDJmVTEVbXQhziskfdGWaNqY3bM45bRZ7lLqqOKLKJJxP5geK vuQw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=FTUIQLG67q4L37zxmd4J6MTyL080A6Y33cHJDWComPQ=; b=dBZdK9ppQ0hMUVuCu/EXU01uGY3QBEmymSwdNEsxNvve2bxhPsO+0bWDO99WEnv0MD DfjLPoZXpz+Ac6rZcFOrhBGcUAp9rseGhPnhRb0JyCqz6lS4ySCcGWnnLrBuwi6NcdoP QxP+oJpbhBowN0DcHYJvgw4N56mH5EFjfYQxzxso7Fig0KHR4syp92pweWY4Xe40P4me tHv2Wz3OGp3Z6c//RjNgxdTXlhlLieKtPIvdubBzUXXWJRl5AWHH/+BwjIuLQ9aS8Q1T U7Tr/JKvFb7jrNUbkD5mtWMqIOgT0KuXpN1H3OAyIDl+aeKejKElHs6jgqOqhFKfLO9+ 7lEA== X-Gm-Message-State: AJIora92PXpYYdSSVndHZ9wToj2js4NeyGMZzWdpJOEjjhwixKA4Qo0i SmoQVE7mu0mMzep3ORiyhUo= X-Google-Smtp-Source: AGRyM1s8RMqIXFXUT8vFnNBm7zERbDjAmqmWOtRgKzXPzBK2GFCSXLypimIlWEdVVgtG1Xhkip2iaw== X-Received: by 2002:adf:f3c7:0:b0:21d:9349:7a5 with SMTP id g7-20020adff3c7000000b0021d934907a5mr9420472wrp.23.1657444736364; Sun, 10 Jul 2022 02:18:56 -0700 (PDT) Received: from xps-work.lan (214.red-83-37-4.dynamicip.rima-tde.net. [83.37.4.214]) by smtp.gmail.com with ESMTPSA id y5-20020adff6c5000000b0021d83071683sm3192747wrp.64.2022.07.10.02.18.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 Jul 2022 02:18:55 -0700 (PDT) From: Angel Iglesias To: Dan Carpenter Cc: Angel Iglesias , kernel test robot , Jonathan Cameron , Lars-Peter Clausen , Ulf Hansson , Paul Cercueil , "Rafael J. Wysocki" , linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 4/5] iio: pressure: bmp280: Add support for BMP380 sensor family Date: Sun, 10 Jul 2022 11:18:31 +0200 Message-Id: <20220710091837.16057-1-ang.iglesiasg@gmail.com> X-Mailer: git-send-email 2.36.1 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Adds compatibility with the new generation of this sensor, the BMP380 Includes basic sensor initialization to do pressure and temp measurements and allows tuning oversampling settings for each channel. The compensation algorithms are adapted from the device datasheet and the repository https://github.com/BoschSensortec/BMP3-Sensor-API Signed-off-by: Angel Iglesias Reported-by: kernel test robot Reported-by: Dan Carpenter --- drivers/iio/pressure/bmp280-core.c | 356 +++++++++++++++++++++++++++ drivers/iio/pressure/bmp280-i2c.c | 5 + drivers/iio/pressure/bmp280-regmap.c | 55 +++++ drivers/iio/pressure/bmp280-spi.c | 5 + drivers/iio/pressure/bmp280.h | 101 ++++++++ 5 files changed, 522 insertions(+) diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c index 59e9c5fb4ab4..5d5d20d97cf6 100644 --- a/drivers/iio/pressure/bmp280-core.c +++ b/drivers/iio/pressure/bmp280-core.c @@ -12,10 +12,13 @@ * https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BMP180-DS000-121.pdf * https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BMP280-DS001-12.pdf * https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BME280_DS001-11.pdf + * https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmp388-ds001.pdf */ #define pr_fmt(fmt) "bmp280: " fmt +#include +#include #include #include #include @@ -29,6 +32,7 @@ #include #include #include +#include #include "bmp280.h" @@ -74,6 +78,24 @@ struct bmp280_calib { s8 H6; }; +/* See datasheet Section 3.11.1. */ +struct bmp380_calib { + u16 T1; + u16 T2; + s8 T3; + s16 P1; + s16 P2; + s8 P3; + s8 P4; + u16 P5; + u16 P6; + s8 P7; + s8 P8; + s16 P9; + s8 P10; + s8 P11; +}; + static const char *const bmp280_supply_names[] = { "vddd", "vdda" }; @@ -90,6 +112,7 @@ struct bmp280_data { union { struct bmp180_calib bmp180; struct bmp280_calib bmp280; + struct bmp380_calib bmp380; } calib; struct regulator_bulk_data supplies[BMP280_NUM_SUPPLIES]; unsigned int start_up_time; /* in microseconds */ @@ -138,6 +161,25 @@ struct bmp280_chip_info { enum { T1, T2, T3 }; enum { P1, P2, P3, P4, P5, P6, P7, P8, P9 }; +enum { + /* Temperature calib indexes */ + BMP380_T1 = 0, + BMP380_T2 = 2, + BMP380_T3 = 4, + /* Pressure calib indexes */ + BMP380_P1 = 5, + BMP380_P2 = 7, + BMP380_P3 = 9, + BMP380_P4 = 10, + BMP380_P5 = 11, + BMP380_P6 = 13, + BMP380_P7 = 15, + BMP380_P8 = 16, + BMP380_P9 = 17, + BMP380_P10 = 19, + BMP380_P11 = 20 +}; + static const struct iio_chan_spec bmp280_channels[] = { { .type = IIO_PRESSURE, @@ -708,6 +750,310 @@ static const struct bmp280_chip_info bme280_chip_info = { .read_calib = bmp280_read_calib, }; +/* Send a command to BMP3XX sensors */ +static int bmp380_cmd(struct bmp280_data *data, u8 cmd) +{ + int ret; + unsigned int reg; + + /* check if device is ready to process a command */ + ret = regmap_read(data->regmap, BMP380_REG_STATUS, ®); + if (ret) { + dev_err(data->dev, "failed to read error register\n"); + return ret; + } + if (!(reg & BMP380_STATUS_CMD_RDY_MASK)) { + dev_err(data->dev, "device is not ready to accept commands\n"); + return -EBUSY; + } + + /* send command to process */ + ret = regmap_write(data->regmap, BMP380_REG_CMD, cmd); + if (ret) { + dev_err(data->dev, "failed to send command to device\n"); + return ret; + } + /* wait for 2ms for command to be proccessed */ + usleep_range(data->start_up_time, data->start_up_time + 100); + /* check for command processing error */ + ret = regmap_read(data->regmap, BMP380_REG_ERROR, ®); + if (ret) { + dev_err(data->dev, "error reading ERROR reg\n"); + return ret; + } + if (reg & BMP380_ERR_CMD_MASK) { + dev_err(data->dev, "error processing command 0x%X\n", cmd); + return -EINVAL; + } + dev_dbg(data->dev, "Command 0x%X proccessed successfully\n", cmd); + + return 0; +} + +/* + * Returns temperature in DegC, resolution is 0.01 DegC. Output value of + * "5123" equals 51.23 DegC. t_fine carries fine temperature as global + * value. + * + * Taken from datasheet, Section Appendix 9, "Compensation formula" and repo + * https://github.com/BoschSensortec/BMP3-Sensor-API + */ +static s32 bmp380_compensate_temp(struct bmp280_data *data, u32 adc_temp) +{ + s64 var1, var2, var3, var4, var5, var6, comp_temp; + struct bmp380_calib *calib = &data->calib.bmp380; + + var1 = ((s64) adc_temp) - (((s64) calib->T1) << 8); + var2 = var1 * ((s64) calib->T2); + var3 = var1 * var1; + var4 = var3 * ((s64) calib->T3); + var5 = (var2 << 18) + var4; + var6 = var5 >> 32; + data->t_fine = (s32) var6; + comp_temp = (var6 * 25) >> 14; + + comp_temp = clamp_val(comp_temp, BMP380_MIN_TEMP, BMP380_MAX_TEMP); + return (s32) comp_temp; +} + +/* + * Returns pressure in Pa as unsigned 32 bit integer in fractional Pascal. + * Output value of "9528709" represents 9528709/100 = 95287.09 Pa = 952.8709 hPa + * + * Taken from datasheet, Section 9.3. "Pressure compensation" and repository + * https://github.com/BoschSensortec/BMP3-Sensor-API + */ +static u32 bmp380_compensate_press(struct bmp280_data *data, u32 adc_press) +{ + s64 var1, var2, var3, var4, var5, var6, offset, sensitivity; + u64 comp_press; + struct bmp380_calib *calib = &data->calib.bmp380; + + var1 = ((s64)data->t_fine) * ((s64)data->t_fine); + var2 = var1 >> 6; + var3 = (var2 * ((s64) data->t_fine)) >> 8; + var4 = (((s64)calib->P8) * var3) >> 5; + var5 = (((s64) calib->P7) * var1) << 4; + var6 = (((s64) calib->P6) * ((s64)data->t_fine)) << 22; + offset = (((s64)calib->P5) << 47) + var4 + var5 + var6; + var2 = (((s64)calib->P4) * var3) >> 5; + var4 = (((s64) calib->P3) * var1) << 2; + var5 = (((s64) calib->P2) - ((s64) 1<<14)) * + (((s64)data->t_fine) << 21); + sensitivity = ((((s64) calib->P1) - ((s64) 1 << 14)) << 46) + + var2 + var4 + var5; + var1 = (sensitivity >> 24) * ((s64)adc_press); + var2 = ((s64)calib->P10) * ((s64) data->t_fine); + var3 = var2 + (((s64) calib->P9) << 16); + var4 = (var3 * ((s64)adc_press)) >> 13; + + /* + * Dividing by 10 followed by multiplying by 10 to avoid + * possible overflow caused by (uncomp_data->pressure * partial_data4) + */ + var5 = (((s64)adc_press) * (var4 / 10)) >> 9; + var5 *= 10; + var6 = ((s64)adc_press) * ((s64)adc_press); + var2 = (((s64)calib->P11) * var6) >> 16; + var3 = (var2 * ((s64)adc_press)) >> 7; + var4 = (offset >> 2) + var1 + var5 + var3; + comp_press = ((u64)var4 * 25) >> 40; + + comp_press = clamp_val(comp_press, BMP380_MIN_PRES, BMP380_MAX_PRES); + return (u32)comp_press; +} + +static int bmp380_read_temp(struct bmp280_data *data, int *val) +{ + int ret; + u8 tmp[3]; + u32 adc_temp; + s32 comp_temp; + + ret = regmap_bulk_read(data->regmap, BMP380_REG_TEMP_XLSB, tmp, 3); + if (ret < 0) { + dev_err(data->dev, "failed to read temperature\n"); + return ret; + } + + adc_temp = get_unaligned_le24(tmp); + if (adc_temp == BMP380_TEMP_SKIPPED) { + /* reading was skipped */ + dev_err(data->dev, "reading temperature skipped\n"); + return -EIO; + } + comp_temp = bmp380_compensate_temp(data, adc_temp); + + /* + * val might be NULL if we're called by the read_press routine, + * who only cares about the carry over t_fine value. + */ + if (val) { + /* IIO reports temperatures in mC */ + *val = comp_temp * 10; + return IIO_VAL_INT; + } + + return 0; +} + +static int bmp380_read_press(struct bmp280_data *data, int *val, int *val2) +{ + int ret; + u8 tmp[3]; + u32 adc_press; + s32 comp_press; + + /* Read and compensate temperature so we get a reading of t_fine. */ + ret = bmp380_read_temp(data, NULL); + if (ret < 0) + return ret; + + ret = regmap_bulk_read(data->regmap, BMP380_REG_PRESS_XLSB, tmp, 3); + if (ret < 0) { + dev_err(data->dev, "failed to read pressure\n"); + return ret; + } + + adc_press = get_unaligned_le24(tmp); + if (adc_press == BMP380_PRESS_SKIPPED) { + /* reading was skipped */ + dev_err(data->dev, "reading pressure skipped\n"); + return -EIO; + } + comp_press = bmp380_compensate_press(data, adc_press); + + *val = comp_press; + /* Compensated pressure is in cPa (centipascals) */ + *val2 = 100000; + + return IIO_VAL_FRACTIONAL; +} + +static int bmp380_read_calib(struct bmp280_data *data, unsigned int chip) +{ + int ret; + struct bmp380_calib *calib = &data->calib.bmp380; + u8 buf[BMP380_CALIB_REG_COUNT]; + + /* Read temperature calibration values. */ + ret = regmap_bulk_read(data->regmap, BMP380_REG_CALIB_TEMP_START, buf, + BMP380_CALIB_REG_COUNT); + if (ret < 0) { + dev_err(data->dev, + "failed to read temperature calibration parameters\n"); + return ret; + } + + /* Toss the temperature calibration data into the entropy pool */ + add_device_randomness(buf, sizeof(buf)); + + /* Parse calibration data */ + calib->T1 = get_unaligned_le16(&buf[BMP380_T1]); + calib->T2 = get_unaligned_le16(&buf[BMP380_T2]); + calib->T3 = buf[BMP380_T3]; + calib->P1 = get_unaligned_le16(&buf[BMP380_P1]); + calib->P2 = get_unaligned_le16(&buf[BMP380_P2]); + calib->P3 = buf[BMP380_P3]; + calib->P4 = buf[BMP380_P4]; + calib->P5 = get_unaligned_le16(&buf[BMP380_P5]); + calib->P6 = get_unaligned_le16(&buf[BMP380_P6]); + calib->P7 = buf[BMP380_P7]; + calib->P8 = buf[BMP380_P8]; + calib->P9 = get_unaligned_le16(&buf[BMP380_P9]); + calib->P10 = buf[BMP380_P10]; + calib->P11 = buf[BMP380_P11]; + + return 0; +} + +static int bmp380_chip_config(struct bmp280_data *data) +{ + unsigned int tmp; + u8 osrs; + int ret; + + /* configure power control register */ + ret = regmap_write_bits(data->regmap, BMP380_REG_POWER_CONTROL, + BMP380_CTRL_SENSORS_MASK | BMP380_MODE_MASK, + BMP380_CTRL_SENSORS_PRESS_EN | + BMP380_CTRL_SENSORS_TEMP_EN | + FIELD_PREP(BMP380_MODE_MASK, BMP380_MODE_NORMAL)); + if (ret < 0) { + dev_err(data->dev, + "failed to write operation control register\n"); + return ret; + } + + /* configure oversampling */ + osrs = FIELD_PREP(BMP380_OSRS_TEMP_MASK, data->oversampling_temp) | + FIELD_PREP(BMP380_OSRS_PRESS_MASK, data->oversampling_press); + + ret = regmap_write_bits(data->regmap, BMP380_REG_OSR, + BMP380_OSRS_TEMP_MASK | BMP380_OSRS_PRESS_MASK, + osrs); + if (ret < 0) { + dev_err(data->dev, "failed to write oversampling register\n"); + return ret; + } + + /* configure output data rate */ + ret = regmap_write_bits(data->regmap, BMP380_REG_ODR, + BMP380_ODRS_MASK, BMP380_ODRS_50HZ); + if (ret < 0) { + dev_err(data->dev, "failed to write ODR selection register\n"); + return ret; + } + + /* set filter data */ + ret = regmap_update_bits(data->regmap, BMP380_REG_CONFIG, + BMP380_FILTER_MASK, + FIELD_PREP(BMP380_FILTER_MASK, BMP380_FILTER_3X)); + if (ret < 0) { + dev_err(data->dev, "failed to write config register\n"); + return ret; + } + + /* wait startup_time before verifying config changes */ + usleep_range(data->start_up_time, data->start_up_time + 100); + + /* check config error flag */ + ret = regmap_read(data->regmap, BMP380_REG_ERROR, &tmp); + if (ret < 0) { + dev_err(data->dev, + "failed to read error register\n"); + return ret; + } + if (tmp & BMP380_ERR_CONF_MASK) { + dev_warn(data->dev, + "sensor flagged configuration as incompatible\n"); + return -EINVAL; + } + + return 0; +} + +static const int bmp380_oversampling_avail[] = { 1, 2, 4, 8, 16, 32 }; + +static const struct bmp280_chip_info bmp380_chip_info = { + .id_reg = BMP380_REG_ID, + .start_up_time = 2000, + .num_channels = 2, + + .oversampling_temp_avail = bmp380_oversampling_avail, + .num_oversampling_temp_avail = ARRAY_SIZE(bmp380_oversampling_avail), + .oversampling_temp_default = ilog2(1), + + .oversampling_press_avail = bmp380_oversampling_avail, + .num_oversampling_press_avail = ARRAY_SIZE(bmp380_oversampling_avail), + .oversampling_press_default = ilog2(4), + + .chip_config = bmp380_chip_config, + .read_temp = bmp380_read_temp, + .read_press = bmp380_read_press, + .read_calib = bmp380_read_calib, +}; + static int bmp180_measure(struct bmp280_data *data, u8 ctrl_meas) { int ret; @@ -1050,6 +1396,9 @@ int bmp280_common_probe(struct device *dev, case BME280_CHIP_ID: chip_info = &bme280_chip_info; break; + case BMP380_CHIP_ID: + chip_info = &bmp380_chip_info; + break; default: return -EINVAL; } @@ -1107,6 +1456,13 @@ int bmp280_common_probe(struct device *dev, return -EINVAL; } + /* BMP3xx requires soft-reset as part of initialization */ + if (chip_id == BMP380_CHIP_ID) { + ret = bmp380_cmd(data, BMP380_CMD_SOFT_RESET); + if (ret < 0) + return ret; + } + ret = data->chip_info->chip_config(data); if (ret < 0) return ret; diff --git a/drivers/iio/pressure/bmp280-i2c.c b/drivers/iio/pressure/bmp280-i2c.c index 35045bd92846..31a8a0daa39a 100644 --- a/drivers/iio/pressure/bmp280-i2c.c +++ b/drivers/iio/pressure/bmp280-i2c.c @@ -19,6 +19,9 @@ static int bmp280_i2c_probe(struct i2c_client *client, case BME280_CHIP_ID: regmap_config = &bmp280_regmap_config; break; + case BMP380_CHIP_ID: + regmap_config = &bmp380_regmap_config; + break; default: return -EINVAL; } @@ -37,6 +40,7 @@ static int bmp280_i2c_probe(struct i2c_client *client, } static const struct of_device_id bmp280_of_i2c_match[] = { + { .compatible = "bosch,bmp380", .data = (void *)BMP380_CHIP_ID }, { .compatible = "bosch,bme280", .data = (void *)BME280_CHIP_ID }, { .compatible = "bosch,bmp280", .data = (void *)BMP280_CHIP_ID }, { .compatible = "bosch,bmp180", .data = (void *)BMP180_CHIP_ID }, @@ -46,6 +50,7 @@ static const struct of_device_id bmp280_of_i2c_match[] = { MODULE_DEVICE_TABLE(of, bmp280_of_i2c_match); static const struct i2c_device_id bmp280_i2c_id[] = { + {"bmp380", BMP380_CHIP_ID }, {"bmp280", BMP280_CHIP_ID }, {"bmp180", BMP180_CHIP_ID }, {"bmp085", BMP180_CHIP_ID }, diff --git a/drivers/iio/pressure/bmp280-regmap.c b/drivers/iio/pressure/bmp280-regmap.c index da136dbadc8f..b440fa41bf12 100644 --- a/drivers/iio/pressure/bmp280-regmap.c +++ b/drivers/iio/pressure/bmp280-regmap.c @@ -72,6 +72,49 @@ static bool bmp280_is_volatile_reg(struct device *dev, unsigned int reg) } } +static bool bmp380_is_writeable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case BMP380_REG_CMD: + case BMP380_REG_CONFIG: + case BMP380_REG_FIFO_CONFIG_1: + case BMP380_REG_FIFO_CONFIG_2: + case BMP380_REG_FIFO_WATERMARK_LSB: + case BMP380_REG_FIFO_WATERMARK_MSB: + case BMP380_REG_POWER_CONTROL: + case BMP380_REG_INT_CONTROL: + case BMP380_REG_IF_CONFIG: + case BMP380_REG_ODR: + case BMP380_REG_OSR: + return true; + default: + return false; + } +} + +static bool bmp380_is_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case BMP380_REG_TEMP_XLSB: + case BMP380_REG_TEMP_LSB: + case BMP380_REG_TEMP_MSB: + case BMP380_REG_PRESS_XLSB: + case BMP380_REG_PRESS_LSB: + case BMP380_REG_PRESS_MSB: + case BMP380_REG_SENSOR_TIME_XLSB: + case BMP380_REG_SENSOR_TIME_LSB: + case BMP380_REG_SENSOR_TIME_MSB: + case BMP380_REG_INT_STATUS: + case BMP380_REG_FIFO_DATA: + case BMP380_REG_STATUS: + case BMP380_REG_ERROR: + case BMP380_REG_EVENT: + return true; + default: + return false; + } +} + const struct regmap_config bmp280_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -83,3 +126,15 @@ const struct regmap_config bmp280_regmap_config = { .volatile_reg = bmp280_is_volatile_reg, }; EXPORT_SYMBOL(bmp280_regmap_config); + +const struct regmap_config bmp380_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = BMP380_REG_CMD, + .cache_type = REGCACHE_RBTREE, + + .writeable_reg = bmp380_is_writeable_reg, + .volatile_reg = bmp380_is_volatile_reg, +}; +EXPORT_SYMBOL(bmp380_regmap_config); diff --git a/drivers/iio/pressure/bmp280-spi.c b/drivers/iio/pressure/bmp280-spi.c index 41f6cc56d229..303c41130343 100644 --- a/drivers/iio/pressure/bmp280-spi.c +++ b/drivers/iio/pressure/bmp280-spi.c @@ -66,6 +66,9 @@ static int bmp280_spi_probe(struct spi_device *spi) case BME280_CHIP_ID: regmap_config = &bmp280_regmap_config; break; + case BMP380_CHIP_ID: + regmap_config = &bmp380_regmap_config; + break; default: return -EINVAL; } @@ -92,6 +95,7 @@ static const struct of_device_id bmp280_of_spi_match[] = { { .compatible = "bosch,bmp181", }, { .compatible = "bosch,bmp280", }, { .compatible = "bosch,bme280", }, + { .compatible = "bosch,bmp380", }, { }, }; MODULE_DEVICE_TABLE(of, bmp280_of_spi_match); @@ -101,6 +105,7 @@ static const struct spi_device_id bmp280_spi_id[] = { { "bmp181", BMP180_CHIP_ID }, { "bmp280", BMP280_CHIP_ID }, { "bme280", BME280_CHIP_ID }, + { "bmp380", BMP380_CHIP_ID }, { } }; MODULE_DEVICE_TABLE(spi, bmp280_spi_id); diff --git a/drivers/iio/pressure/bmp280.h b/drivers/iio/pressure/bmp280.h index 57ba0e85db91..fd38906c889c 100644 --- a/drivers/iio/pressure/bmp280.h +++ b/drivers/iio/pressure/bmp280.h @@ -3,6 +3,105 @@ #include #include +/* BMP380 specific registers */ +#define BMP380_REG_CMD 0x7E +#define BMP380_REG_CONFIG 0x1F +#define BMP380_REG_ODR 0X1D +#define BMP380_REG_OSR 0X1C +#define BMP380_REG_POWER_CONTROL 0X1B +#define BMP380_REG_IF_CONFIG 0X1A +#define BMP380_REG_INT_CONTROL 0X19 +#define BMP380_REG_INT_STATUS 0X11 +#define BMP380_REG_EVENT 0X10 +#define BMP380_REG_STATUS 0X03 +#define BMP380_REG_ERROR 0X02 +#define BMP380_REG_ID 0X00 + +#define BMP380_REG_FIFO_CONFIG_1 0X18 +#define BMP380_REG_FIFO_CONFIG_2 0X17 +#define BMP380_REG_FIFO_WATERMARK_MSB 0X16 +#define BMP380_REG_FIFO_WATERMARK_LSB 0X15 +#define BMP380_REG_FIFO_DATA 0X14 +#define BMP380_REG_FIFO_LENGTH_MSB 0X13 +#define BMP380_REG_FIFO_LENGTH_LSB 0X12 + +#define BMP380_REG_SENSOR_TIME_MSB 0X0E +#define BMP380_REG_SENSOR_TIME_LSB 0X0D +#define BMP380_REG_SENSOR_TIME_XLSB 0X0C + +#define BMP380_REG_TEMP_MSB 0X09 +#define BMP380_REG_TEMP_LSB 0X08 +#define BMP380_REG_TEMP_XLSB 0X07 + +#define BMP380_REG_PRESS_MSB 0X06 +#define BMP380_REG_PRESS_LSB 0X05 +#define BMP380_REG_PRESS_XLSB 0X04 + +#define BMP380_REG_CALIB_TEMP_START 0x31 +#define BMP380_CALIB_REG_COUNT 21 + +#define BMP380_FILTER_MASK GENMASK(3, 1) +#define BMP380_FILTER_OFF 0 +#define BMP380_FILTER_1X 1 +#define BMP380_FILTER_3X 2 +#define BMP380_FILTER_7X 3 +#define BMP380_FILTER_15X 4 +#define BMP380_FILTER_31X 5 +#define BMP380_FILTER_63X 6 +#define BMP380_FILTER_127X 7 + +#define BMP380_OSRS_TEMP_MASK GENMASK(5, 3) +#define BMP380_OSRS_PRESS_MASK GENMASK(2, 0) + +#define BMP380_ODRS_MASK GENMASK(4, 0) +#define BMP380_ODRS_200HZ 0x00 +#define BMP380_ODRS_100HZ 0x01 +#define BMP380_ODRS_50HZ 0x02 +#define BMP380_ODRS_25HZ 0x03 +#define BMP380_ODRS_12_5HZ 0x04 +#define BMP380_ODRS_6_25HZ 0x05 +#define BMP380_ODRS_3_1HZ 0x06 +#define BMP380_ODRS_1_5HZ 0x07 +#define BMP380_ODRS_0_78HZ 0x08 +#define BMP380_ODRS_0_39HZ 0x09 +#define BMP380_ODRS_0_2HZ 0x0A +#define BMP380_ODRS_0_1HZ 0x0B +#define BMP380_ODRS_0_05HZ 0x0C +#define BMP380_ODRS_0_02HZ 0x0D +#define BMP380_ODRS_0_01HZ 0x0E +#define BMP380_ODRS_0_006HZ 0x0F +#define BMP380_ODRS_0_003HZ 0x10 +#define BMP380_ODRS_0_0015HZ 0x11 + +#define BMP380_CTRL_SENSORS_MASK GENMASK(1, 0) +#define BMP380_CTRL_SENSORS_PRESS_EN BIT(0) +#define BMP380_CTRL_SENSORS_TEMP_EN BIT(1) +#define BMP380_MODE_MASK GENMASK(5, 4) +#define BMP380_MODE_SLEEP 0 +#define BMP380_MODE_FORCED 1 +#define BMP380_MODE_NORMAL 3 + +#define BMP380_MIN_TEMP -4000 +#define BMP380_MAX_TEMP 8500 +#define BMP380_MIN_PRES 3000000 +#define BMP380_MAX_PRES 12500000 + +#define BMP380_CMD_NOOP 0X00 +#define BMP380_CMD_EXTMODE_EN_MID 0x34 +#define BMP380_CMD_FIFO_FLUSH 0XB0 +#define BMP380_CMD_SOFT_RESET 0xB6 + +#define BMP380_STATUS_CMD_RDY_MASK BIT(4) +#define BMP380_STATUS_DRDY_PRESS_MASK BIT(5) +#define BMP380_STATUS_DRDY_TEMP_MASK BIT(6) + +#define BMP380_ERR_FATAL_MASK BIT(0) +#define BMP380_ERR_CMD_MASK BIT(1) +#define BMP380_ERR_CONF_MASK BIT(2) + +#define BMP380_TEMP_SKIPPED 0x800000 +#define BMP380_PRESS_SKIPPED 0x800000 + /* BMP280 specific registers */ #define BMP280_REG_HUMIDITY_LSB 0xFE #define BMP280_REG_HUMIDITY_MSB 0xFD @@ -92,6 +191,7 @@ #define BMP280_REG_RESET 0xE0 #define BMP280_REG_ID 0xD0 +#define BMP380_CHIP_ID 0x50 #define BMP180_CHIP_ID 0x55 #define BMP280_CHIP_ID 0x58 #define BME280_CHIP_ID 0x60 @@ -105,6 +205,7 @@ /* Regmap configurations */ extern const struct regmap_config bmp180_regmap_config; extern const struct regmap_config bmp280_regmap_config; +extern const struct regmap_config bmp380_regmap_config; /* Probe called from different transports */ int bmp280_common_probe(struct device *dev, From patchwork Sun Jul 10 09:20:16 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angel Iglesias X-Patchwork-Id: 12912494 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B3822C433EF for ; Sun, 10 Jul 2022 09:21:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229544AbiGJJVD (ORCPT ); Sun, 10 Jul 2022 05:21:03 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43802 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229505AbiGJJVB (ORCPT ); Sun, 10 Jul 2022 05:21:01 -0400 Received: from mail-wm1-x332.google.com (mail-wm1-x332.google.com [IPv6:2a00:1450:4864:20::332]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 85595DFC8; Sun, 10 Jul 2022 02:20:59 -0700 (PDT) Received: by mail-wm1-x332.google.com with SMTP id n185so1508394wmn.4; Sun, 10 Jul 2022 02:20:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=QLeB5uPaH4ZkqLTkyHhLPzDyUc7lgVAMRLQMDpNtsWc=; b=Ry7bMI5sTTj8yJkQJbizZh1nhnE4aJimG0eUU2RSJeggBzT5zsbdb0aFS5MYJhXHw1 OR0BEe1dfv66Km01YWzwJ3TUOnvffdPfLU4/5GpHNlCHUpYPIY/Mlc8v0L10b2dst9Ji eihbXF63w7npEFhS5bXdoMMOGzbAPfkWhptyNOuYIoEGNWpfCIwZd+E1+XE+E0dDeVwI yVzIFw+bQgysGnX1Z/dFH8eohb0lxFh3b5Llea3UsTgRjzKj0eyXzMk68K5WyX4KPB04 FezHvVB99zQa+L0ae4tq/TNai1ZK8aWenWXGr3PjUh0z3VgxmENzrHqi02HX6UDJyea4 oreQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=QLeB5uPaH4ZkqLTkyHhLPzDyUc7lgVAMRLQMDpNtsWc=; b=T2a3Hkwv4WU5afTvLSNQ9jeIGBoLxqBdUz8GT0c1kdl/GY8va8dl5TMi46QpG0o6nh SGDlK4RKu7xXxRN+6hAVTVJysiFFvRbtV8IuzCZ9xwVFYjRsLE9jWGU5RekWZ++fQdTp kxy1LTfP9TiiKuqmqgwPkeILReByUr/zMgVYkEprIYRlfR6TKowNAIPtcgieLqezR5NG /dtJS3U2dr6lebHsL7iE5gIKuLxtQEt5hkMXfnLZ4+CVHhIGKIIC/QTcpvRFls91//Fu AB4zeZcMPVkg1lEZ+II6kk/e0ubCAbjxpR+pIylmxEQNoRLmTD80rySiNiMWey6L/ZqY pKfA== X-Gm-Message-State: AJIora+XFiR35Ry4wLKjHa1R9bY2vYeU61Gu3h/18SHNv/I32qgV8J9v eSTcJWTOkeXCYJrck+LuE4c= X-Google-Smtp-Source: AGRyM1ualhHrGMsvqDVHAhJP4CTs7VNq3ZFpb2LxeNfzPhsJmEo38nKz7QIB+twUv1bpig/YvdVZgg== X-Received: by 2002:a05:600c:4f42:b0:3a0:57ed:93a9 with SMTP id m2-20020a05600c4f4200b003a057ed93a9mr9541723wmq.143.1657444858023; Sun, 10 Jul 2022 02:20:58 -0700 (PDT) Received: from xps-work.lan (214.red-83-37-4.dynamicip.rima-tde.net. [83.37.4.214]) by smtp.gmail.com with ESMTPSA id p13-20020a1c740d000000b0039c5642e430sm3444922wmc.20.2022.07.10.02.20.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 Jul 2022 02:20:57 -0700 (PDT) From: Angel Iglesias To: Andy Shevchenko Cc: Angel Iglesias , Jonathan Cameron , Lars-Peter Clausen , Ulf Hansson , "Rafael J. Wysocki" , Paul Cercueil , linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 5/5] iio: pressure: bmp280: Add more tunable config parameters for BMP380 Date: Sun, 10 Jul 2022 11:20:16 +0200 Message-Id: <20220710092019.16192-1-ang.iglesiasg@gmail.com> X-Mailer: git-send-email 2.36.1 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Allows sampling frequency and IIR filter coefficients configuration using sysfs ABI. The IIR filter coefficient is configurable using the sysfs attribute "filter_low_pass_3db_frequency". Signed-off-by: Angel Iglesias Reported-by: Andy Shevchenko --- drivers/iio/pressure/bmp280-core.c | 324 ++++++++++++++++++++++++++--- drivers/iio/pressure/bmp280.h | 18 -- 2 files changed, 294 insertions(+), 48 deletions(-) diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c index 5d5d20d97cf6..b99f22831a83 100644 --- a/drivers/iio/pressure/bmp280-core.c +++ b/drivers/iio/pressure/bmp280-core.c @@ -100,6 +100,27 @@ static const char *const bmp280_supply_names[] = { "vddd", "vdda" }; +enum bmp380_odr { + BMP380_ODR_200HZ, + BMP380_ODR_100HZ, + BMP380_ODR_50HZ, + BMP380_ODR_25HZ, + BMP380_ODR_12_5HZ, + BMP380_ODR_6_25HZ, + BMP380_ODR_3_125HZ, + BMP380_ODR_1_5625HZ, + BMP380_ODR_0_78HZ, + BMP380_ODR_0_39HZ, + BMP380_ODR_0_2HZ, + BMP380_ODR_0_1HZ, + BMP380_ODR_0_05HZ, + BMP380_ODR_0_02HZ, + BMP380_ODR_0_01HZ, + BMP380_ODR_0_006HZ, + BMP380_ODR_0_003HZ, + BMP380_ODR_0_0015HZ, +}; + #define BMP280_NUM_SUPPLIES ARRAY_SIZE(bmp280_supply_names) struct bmp280_data { @@ -121,6 +142,17 @@ struct bmp280_data { u8 oversampling_press; u8 oversampling_temp; u8 oversampling_humid; + u8 iir_filter_coeff; + + /* + * BMP380 devices introduce sampling frequency configuration. See + * datasheet sections 3.3.3. and 4.3.19 for more details. + * + * BMx280 devices allowed indirect configuration of sampling frequency + * changing the t_standby duration between measurements, as detailed on + * section 3.6.3 of the datasheet. + */ + int sampling_freq; /* * Carryover value from temperature conversion, used in pressure @@ -132,6 +164,7 @@ struct bmp280_data { struct bmp280_chip_info { unsigned int id_reg; + const struct iio_chan_spec *channels; int num_channels; unsigned int start_up_time; @@ -147,6 +180,14 @@ struct bmp280_chip_info { int num_oversampling_humid_avail; int oversampling_humid_default; + const int *iir_filter_coeffs_avail; + int num_iir_filter_coeffs_avail; + int iir_filter_coeff_default; + + const int (*sampling_freq_avail)[2]; + int num_sampling_freq_avail; + int sampling_freq_default; + int (*chip_config)(struct bmp280_data *); int (*read_temp)(struct bmp280_data *, int *); int (*read_press)(struct bmp280_data *, int *, int *); @@ -198,6 +239,30 @@ static const struct iio_chan_spec bmp280_channels[] = { }, }; +static const struct iio_chan_spec bmp380_channels[] = { + { + .type = IIO_PRESSURE, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ) | + BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), + }, + { + .type = IIO_TEMP, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ) | + BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), + }, + { + .type = IIO_HUMIDITYRELATIVE, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ) | + BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), + }, +}; + static int bmp280_read_calib(struct bmp280_data *data, unsigned int chip) { int ret; @@ -525,6 +590,25 @@ static int bmp280_read_raw(struct iio_dev *indio_dev, break; } break; + case IIO_CHAN_INFO_SAMP_FREQ: + if (!data->chip_info->sampling_freq_avail) { + ret = -EINVAL; + break; + } + + *val = data->chip_info->sampling_freq_avail[data->sampling_freq][0]; + *val2 = data->chip_info->sampling_freq_avail[data->sampling_freq][1]; + ret = IIO_VAL_INT_PLUS_MICRO; + break; + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + if (!data->chip_info->iir_filter_coeffs_avail) { + ret = -EINVAL; + break; + } + + *val = data->chip_info->iir_filter_coeffs_avail[data->iir_filter_coeff]; + ret = IIO_VAL_INT; + break; default: ret = -EINVAL; break; @@ -541,14 +625,22 @@ static int bmp280_write_oversampling_ratio_humid(struct bmp280_data *data, int val) { int i; + int ret, prev; const int *avail = data->chip_info->oversampling_humid_avail; const int n = data->chip_info->num_oversampling_humid_avail; for (i = 0; i < n; i++) { if (avail[i] == val) { + prev = data->oversampling_humid; data->oversampling_humid = ilog2(val); - return data->chip_info->chip_config(data); + ret = data->chip_info->chip_config(data); + if (ret) { + data->oversampling_humid = prev; + data->chip_info->chip_config(data); + return ret; + } + return 0; } } return -EINVAL; @@ -558,14 +650,22 @@ static int bmp280_write_oversampling_ratio_temp(struct bmp280_data *data, int val) { int i; + int ret, prev; const int *avail = data->chip_info->oversampling_temp_avail; const int n = data->chip_info->num_oversampling_temp_avail; for (i = 0; i < n; i++) { if (avail[i] == val) { + prev = data->oversampling_temp; data->oversampling_temp = ilog2(val); - return data->chip_info->chip_config(data); + ret = data->chip_info->chip_config(data); + if (ret) { + data->oversampling_temp = prev; + data->chip_info->chip_config(data); + return ret; + } + return 0; } } return -EINVAL; @@ -575,14 +675,72 @@ static int bmp280_write_oversampling_ratio_press(struct bmp280_data *data, int val) { int i; + int ret, prev; const int *avail = data->chip_info->oversampling_press_avail; const int n = data->chip_info->num_oversampling_press_avail; for (i = 0; i < n; i++) { if (avail[i] == val) { + prev = data->oversampling_press; data->oversampling_press = ilog2(val); - return data->chip_info->chip_config(data); + ret = data->chip_info->chip_config(data); + if (ret) { + data->oversampling_press = prev; + data->chip_info->chip_config(data); + return ret; + } + return 0; + } + } + return -EINVAL; +} + +static int bmp280_write_sampling_frequency(struct bmp280_data *data, + int val, int val2) +{ + int i; + int ret, prev; + const int (*avail)[2] = data->chip_info->sampling_freq_avail; + const int n = data->chip_info->num_sampling_freq_avail; + + for (i = 0; i < n; i++) { + if (avail[i][0] == val && avail[i][1] == val2) { + prev = data->sampling_freq; + data->sampling_freq = i; + + ret = data->chip_info->chip_config(data); + if (ret) { + data->sampling_freq = prev; + data->chip_info->chip_config(data); + return ret; + } + return 0; + } + } + return -EINVAL; +} + +static int bmp280_write_iir_filter_coeffs(struct bmp280_data *data, int val) +{ + int i; + int ret, prev; + const int *avail = data->chip_info->iir_filter_coeffs_avail; + const int n = data->chip_info->num_iir_filter_coeffs_avail; + + for (i = 0; i < n; i++) { + if (avail[i] == val) { + prev = data->iir_filter_coeff; + data->iir_filter_coeff = i; + + ret = data->chip_info->chip_config(data); + if (ret) { + data->iir_filter_coeff = prev; + data->chip_info->chip_config(data); + return ret; + + } + return 0; } } return -EINVAL; @@ -595,6 +753,12 @@ static int bmp280_write_raw(struct iio_dev *indio_dev, int ret = 0; struct bmp280_data *data = iio_priv(indio_dev); + /* + * Auxiliar functions to update sensor running configuration. + * If an error happens applying new settings, will try restore + * previous parameters to ensure the sensor is left in a known + * working configuration. + */ switch (mask) { case IIO_CHAN_INFO_OVERSAMPLING_RATIO: pm_runtime_get_sync(data->dev); @@ -617,6 +781,22 @@ static int bmp280_write_raw(struct iio_dev *indio_dev, pm_runtime_mark_last_busy(data->dev); pm_runtime_put_autosuspend(data->dev); break; + case IIO_CHAN_INFO_SAMP_FREQ: + pm_runtime_get_sync(data->dev); + mutex_lock(&data->lock); + ret = bmp280_write_sampling_frequency(data, val, val2); + mutex_unlock(&data->lock); + pm_runtime_mark_last_busy(data->dev); + pm_runtime_put_autosuspend(data->dev); + break; + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + pm_runtime_get_sync(data->dev); + mutex_lock(&data->lock); + ret = bmp280_write_iir_filter_coeffs(data, val); + mutex_unlock(&data->lock); + pm_runtime_mark_last_busy(data->dev); + pm_runtime_put_autosuspend(data->dev); + break; default: return -EINVAL; } @@ -647,6 +827,17 @@ static int bmp280_read_avail(struct iio_dev *indio_dev, } *type = IIO_VAL_INT; return IIO_AVAIL_LIST; + case IIO_CHAN_INFO_SAMP_FREQ: + *vals = (const int *)data->chip_info->sampling_freq_avail; + *type = IIO_VAL_INT_PLUS_MICRO; + /* Values are stored in a 2D matrix */ + *length = data->chip_info->num_sampling_freq_avail; + return IIO_AVAIL_LIST; + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + *vals = data->chip_info->iir_filter_coeffs_avail; + *type = IIO_VAL_INT; + *length = data->chip_info->num_iir_filter_coeffs_avail; + return IIO_AVAIL_LIST; default: return -EINVAL; } @@ -692,6 +883,7 @@ static const int bmp280_oversampling_avail[] = { 1, 2, 4, 8, 16 }; static const struct bmp280_chip_info bmp280_chip_info = { .id_reg = BMP280_REG_ID, .start_up_time = 2000, + .channels = bmp280_channels, .num_channels = 2, .oversampling_temp_avail = bmp280_oversampling_avail, @@ -729,6 +921,7 @@ static int bme280_chip_config(struct bmp280_data *data) static const struct bmp280_chip_info bme280_chip_info = { .id_reg = BMP280_REG_ID, .start_up_time = 2000, + .channels = bmp280_channels, .num_channels = 3, .oversampling_temp_avail = bmp280_oversampling_avail, @@ -967,18 +1160,39 @@ static int bmp380_read_calib(struct bmp280_data *data, unsigned int chip) return 0; } +static const int bmp380_odr_table[][2] = { + [BMP380_ODR_200HZ] = {200, 0}, + [BMP380_ODR_100HZ] = {100, 0}, + [BMP380_ODR_50HZ] = {50, 0}, + [BMP380_ODR_25HZ] = {25, 0}, + [BMP380_ODR_12_5HZ] = {12, 500000}, + [BMP380_ODR_6_25HZ] = {6, 250000}, + [BMP380_ODR_3_125HZ] = {3, 125000}, + [BMP380_ODR_1_5625HZ] = {1, 562500}, + [BMP380_ODR_0_78HZ] = {0, 781250}, + [BMP380_ODR_0_39HZ] = {0, 390625}, + [BMP380_ODR_0_2HZ] = {0, 195313}, + [BMP380_ODR_0_1HZ] = {0, 97656}, + [BMP380_ODR_0_05HZ] = {0, 48828}, + [BMP380_ODR_0_02HZ] = {0, 24414}, + [BMP380_ODR_0_01HZ] = {0, 12207}, + [BMP380_ODR_0_006HZ] = {0, 6104}, + [BMP380_ODR_0_003HZ] = {0, 3052}, + [BMP380_ODR_0_0015HZ] = {0, 1526}, +}; + static int bmp380_chip_config(struct bmp280_data *data) { + bool change = false, aux; unsigned int tmp; u8 osrs; int ret; /* configure power control register */ - ret = regmap_write_bits(data->regmap, BMP380_REG_POWER_CONTROL, - BMP380_CTRL_SENSORS_MASK | BMP380_MODE_MASK, - BMP380_CTRL_SENSORS_PRESS_EN | - BMP380_CTRL_SENSORS_TEMP_EN | - FIELD_PREP(BMP380_MODE_MASK, BMP380_MODE_NORMAL)); + ret = regmap_update_bits(data->regmap, BMP380_REG_POWER_CONTROL, + BMP380_CTRL_SENSORS_MASK, + BMP380_CTRL_SENSORS_PRESS_EN | + BMP380_CTRL_SENSORS_TEMP_EN); if (ret < 0) { dev_err(data->dev, "failed to write operation control register\n"); @@ -989,55 +1203,94 @@ static int bmp380_chip_config(struct bmp280_data *data) osrs = FIELD_PREP(BMP380_OSRS_TEMP_MASK, data->oversampling_temp) | FIELD_PREP(BMP380_OSRS_PRESS_MASK, data->oversampling_press); - ret = regmap_write_bits(data->regmap, BMP380_REG_OSR, - BMP380_OSRS_TEMP_MASK | BMP380_OSRS_PRESS_MASK, - osrs); + ret = regmap_update_bits_check(data->regmap, BMP380_REG_OSR, + BMP380_OSRS_TEMP_MASK | + BMP380_OSRS_PRESS_MASK, + osrs, &aux); if (ret < 0) { dev_err(data->dev, "failed to write oversampling register\n"); return ret; } + change = change || aux; /* configure output data rate */ - ret = regmap_write_bits(data->regmap, BMP380_REG_ODR, - BMP380_ODRS_MASK, BMP380_ODRS_50HZ); + ret = regmap_update_bits_check(data->regmap, BMP380_REG_ODR, + BMP380_ODRS_MASK, data->sampling_freq, + &aux); if (ret < 0) { dev_err(data->dev, "failed to write ODR selection register\n"); return ret; } + change = change || aux; /* set filter data */ - ret = regmap_update_bits(data->regmap, BMP380_REG_CONFIG, - BMP380_FILTER_MASK, - FIELD_PREP(BMP380_FILTER_MASK, BMP380_FILTER_3X)); + ret = regmap_update_bits_check(data->regmap, BMP380_REG_CONFIG, + BMP380_FILTER_MASK, + FIELD_PREP(BMP380_FILTER_MASK, data->iir_filter_coeff), + &aux); if (ret < 0) { dev_err(data->dev, "failed to write config register\n"); return ret; } + change = change || aux; - /* wait startup_time before verifying config changes */ - usleep_range(data->start_up_time, data->start_up_time + 100); + if (change) { + /* + * Configuration errors are detected on the fly during a measurement + * cycle. If the sampling frequency is too low, it's faster to reset + * measurement loop than wait until next measurement is due. + * + * Resets sensor measurement loop toggling between sleep and normal + * operating modes. + */ + ret = regmap_write_bits(data->regmap, BMP380_REG_POWER_CONTROL, + BMP380_MODE_MASK, + FIELD_PREP(BMP380_MODE_MASK, + BMP380_MODE_SLEEP)); + if (ret < 0) { + dev_err(data->dev, "failed to set sleep mode\n"); + return ret; + } + usleep_range(2000, 2500); + ret = regmap_write_bits(data->regmap, BMP380_REG_POWER_CONTROL, + BMP380_MODE_MASK, + FIELD_PREP(BMP380_MODE_MASK, + BMP380_MODE_NORMAL)); + if (ret < 0) { + dev_err(data->dev, "failed to set normal mode\n"); + return ret; + } + /* + * Waits for measurement before checking configuration error flag. + * Selected longest measure time indicated in section 3.9.1 + * in the datasheet. + */ + msleep(80); - /* check config error flag */ - ret = regmap_read(data->regmap, BMP380_REG_ERROR, &tmp); - if (ret < 0) { - dev_err(data->dev, - "failed to read error register\n"); - return ret; - } - if (tmp & BMP380_ERR_CONF_MASK) { - dev_warn(data->dev, - "sensor flagged configuration as incompatible\n"); - return -EINVAL; + /* check config error flag */ + ret = regmap_read(data->regmap, BMP380_REG_ERROR, &tmp); + if (ret < 0) { + dev_err(data->dev, + "failed to read error register\n"); + return ret; + } + if (tmp & BMP380_ERR_CONF_MASK) { + dev_warn(data->dev, + "sensor flagged configuration as incompatible\n"); + return -EINVAL; + } } return 0; } static const int bmp380_oversampling_avail[] = { 1, 2, 4, 8, 16, 32 }; +static const int bmp380_iir_filter_coeffs_avail[] = { 0, 1, 3, 7, 15, 31, 63, 127 }; static const struct bmp280_chip_info bmp380_chip_info = { .id_reg = BMP380_REG_ID, .start_up_time = 2000, + .channels = bmp380_channels, .num_channels = 2, .oversampling_temp_avail = bmp380_oversampling_avail, @@ -1048,6 +1301,14 @@ static const struct bmp280_chip_info bmp380_chip_info = { .num_oversampling_press_avail = ARRAY_SIZE(bmp380_oversampling_avail), .oversampling_press_default = ilog2(4), + .sampling_freq_avail = bmp380_odr_table, + .num_sampling_freq_avail = ARRAY_SIZE(bmp380_odr_table) * 2, + .sampling_freq_default = BMP380_ODR_50HZ, + + .iir_filter_coeffs_avail = bmp380_iir_filter_coeffs_avail, + .num_iir_filter_coeffs_avail = ARRAY_SIZE(bmp380_iir_filter_coeffs_avail), + .iir_filter_coeff_default = 2, + .chip_config = bmp380_chip_config, .read_temp = bmp380_read_temp, .read_press = bmp380_read_press, @@ -1284,6 +1545,7 @@ static const int bmp180_oversampling_press_avail[] = { 1, 2, 4, 8 }; static const struct bmp280_chip_info bmp180_chip_info = { .id_reg = BMP280_REG_ID, .start_up_time = 2000, + .channels = bmp280_channels, .num_channels = 2, .oversampling_temp_avail = bmp180_oversampling_temp_avail, @@ -1382,7 +1644,6 @@ int bmp280_common_probe(struct device *dev, data->dev = dev; indio_dev->name = name; - indio_dev->channels = bmp280_channels; indio_dev->info = &bmp280_info; indio_dev->modes = INDIO_DIRECT_MODE; @@ -1405,10 +1666,13 @@ int bmp280_common_probe(struct device *dev, data->chip_info = chip_info; /* apply initial values from chip info structure */ + indio_dev->channels = chip_info->channels; indio_dev->num_channels = chip_info->num_channels; data->oversampling_press = chip_info->oversampling_press_default; data->oversampling_humid = chip_info->oversampling_humid_default; data->oversampling_temp = chip_info->oversampling_temp_default; + data->iir_filter_coeff = chip_info->iir_filter_coeff_default; + data->sampling_freq = chip_info->sampling_freq_default; data->start_up_time = chip_info->start_up_time; /* Bring up regulators */ diff --git a/drivers/iio/pressure/bmp280.h b/drivers/iio/pressure/bmp280.h index fd38906c889c..1314d5059c53 100644 --- a/drivers/iio/pressure/bmp280.h +++ b/drivers/iio/pressure/bmp280.h @@ -54,24 +54,6 @@ #define BMP380_OSRS_PRESS_MASK GENMASK(2, 0) #define BMP380_ODRS_MASK GENMASK(4, 0) -#define BMP380_ODRS_200HZ 0x00 -#define BMP380_ODRS_100HZ 0x01 -#define BMP380_ODRS_50HZ 0x02 -#define BMP380_ODRS_25HZ 0x03 -#define BMP380_ODRS_12_5HZ 0x04 -#define BMP380_ODRS_6_25HZ 0x05 -#define BMP380_ODRS_3_1HZ 0x06 -#define BMP380_ODRS_1_5HZ 0x07 -#define BMP380_ODRS_0_78HZ 0x08 -#define BMP380_ODRS_0_39HZ 0x09 -#define BMP380_ODRS_0_2HZ 0x0A -#define BMP380_ODRS_0_1HZ 0x0B -#define BMP380_ODRS_0_05HZ 0x0C -#define BMP380_ODRS_0_02HZ 0x0D -#define BMP380_ODRS_0_01HZ 0x0E -#define BMP380_ODRS_0_006HZ 0x0F -#define BMP380_ODRS_0_003HZ 0x10 -#define BMP380_ODRS_0_0015HZ 0x11 #define BMP380_CTRL_SENSORS_MASK GENMASK(1, 0) #define BMP380_CTRL_SENSORS_PRESS_EN BIT(0)