From patchwork Sun Dec 25 16:56:07 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angel Iglesias X-Patchwork-Id: 13081509 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 3383DC3DA7A for ; Sun, 25 Dec 2022 16:56:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229445AbiLYQ4u (ORCPT ); Sun, 25 Dec 2022 11:56:50 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41458 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229861AbiLYQ4t (ORCPT ); Sun, 25 Dec 2022 11:56:49 -0500 Received: from mail-wr1-x42d.google.com (mail-wr1-x42d.google.com [IPv6:2a00:1450:4864:20::42d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AC6BF2708; Sun, 25 Dec 2022 08:56:48 -0800 (PST) Received: by mail-wr1-x42d.google.com with SMTP id y16so8576180wrm.2; Sun, 25 Dec 2022 08:56:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Pcll64ajG15YCYg/EASo/QQIv8iNSJ6vRhknnam6qyo=; b=ASoVHuWVqUHNXmzaiP5MtnjorTVoj+JpHGsuJr+fsSsgrAMiHY1q5RySreu6xJROW1 tnAOAPPVQ6K5ENgDzc9Hx8wCb5mADBsYiSznNkOT5if8hBdTvfAwKcHcy9FI9GlFcc9p HutiZ/6EncVZkUTR8Da5km5mvegm8mVkla7h4cvV2V1wsH1EemDW/8SIIh8Boi0rVKqh Af6wRj4DQUWOr5kYUqUqv8cYWIuMX15rvsJzWwtO5yl2vzCZjlQ5iJzeuzSr1riLqJ+c vMUsICk7EngzO86RRNRAlcy5Rpb2HBDe993UEd1IwLGT+Xk6T4hA90FbYuYT2mJ1R5M6 tt5A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Pcll64ajG15YCYg/EASo/QQIv8iNSJ6vRhknnam6qyo=; b=GxTm0yNOCxHTmmve/LGW90fDP2962kElYNVSN0Bx5XupdQiXlz3GenQMnSovu8c5kx NDnZbGXnDwlufgGifa5MI3UASxuxNULCyKNYGzjqdSAiIfVYr/+39HU4Xz0KMWsZWG46 vQlhBA0BKMz8YGgs4cXamWw1NxCi7UrMiWW3KKUXwljnQY3idonJqisydzfuJHW8j5Ur tvyhh5OPaFw6J66faNcMkRKKApB/fysGFwPC5E5+fFhj799F8Ba+k1kyrYFG9vliLUzw khPKwVB5rbJ2bdZS0A5uNsPa5MnEcBPI5BP+ayNLBxl3n6MSIWP5aCQaSYz70KMHRCeh /6tw== X-Gm-Message-State: AFqh2kp2U8fqGQHtinqv8NixjH+emy5LQ5aR0SnNupAujVIRT60pdyiT HHhastC1g/+xWzeL0qbzFQdmay+r1iw= X-Google-Smtp-Source: AMrXdXs4LY32HhVvWvbPnnoY0pZ84grSLIhD+Q5AXCNfb53Voxc2rQnqvS1OmlBB6A/bxD7WnOHjmQ== X-Received: by 2002:adf:f9d1:0:b0:254:3dcb:dbb3 with SMTP id w17-20020adff9d1000000b002543dcbdbb3mr9942977wrr.53.1671987406930; Sun, 25 Dec 2022 08:56:46 -0800 (PST) Received: from localhost.localdomain (188.red-83-35-57.dynamicip.rima-tde.net. [83.35.57.188]) by smtp.gmail.com with ESMTPSA id l3-20020a05600012c300b00236c1f2cecesm9470874wrx.81.2022.12.25.08.56.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 25 Dec 2022 08:56:46 -0800 (PST) From: Angel Iglesias To: linux-iio@vger.kernel.org Cc: Angel Iglesias , Jonathan Cameron , Lars-Peter Clausen , Ulf Hansson , "Rafael J. Wysocki" , Paul Cercueil , Andy Shevchenko , linux-kernel@vger.kernel.org Subject: [PATCH 1/5] iio: pressure: bmp280: Add enumeration to handle chip variants Date: Sun, 25 Dec 2022 17:56:07 +0100 Message-Id: X-Mailer: git-send-email 2.39.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Adds enumeration to improve handling the different supported sensors on driver initialization. This avoid collisions if different variants share the same device idetifier on ID register. Signed-off-by: Angel Iglesias diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c index c0aff78489b4..46959a91408f 100644 --- a/drivers/iio/pressure/bmp280-core.c +++ b/drivers/iio/pressure/bmp280-core.c @@ -186,6 +186,7 @@ struct bmp280_data { struct bmp280_chip_info { unsigned int id_reg; + const unsigned int chip_id; const struct iio_chan_spec *channels; int num_channels; @@ -907,6 +908,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, + .chip_id = BMP280_CHIP_ID, .start_up_time = 2000, .channels = bmp280_channels, .num_channels = 2, @@ -955,6 +957,7 @@ static int bme280_chip_config(struct bmp280_data *data) static const struct bmp280_chip_info bme280_chip_info = { .id_reg = BMP280_REG_ID, + .chip_id = BME280_CHIP_ID, .start_up_time = 2000, .channels = bmp280_channels, .num_channels = 3, @@ -1321,6 +1324,7 @@ static const int bmp380_iir_filter_coeffs_avail[] = { 1, 2, 4, 8, 16, 32, 64, 12 static const struct bmp280_chip_info bmp380_chip_info = { .id_reg = BMP380_REG_ID, + .chip_id = BMP380_CHIP_ID, .start_up_time = 2000, .channels = bmp380_channels, .num_channels = 2, @@ -1581,6 +1585,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, + .chip_id = BMP180_CHIP_ID, .start_up_time = 2000, .channels = bmp280_channels, .num_channels = 2, @@ -1685,16 +1690,16 @@ int bmp280_common_probe(struct device *dev, indio_dev->modes = INDIO_DIRECT_MODE; switch (chip) { - case BMP180_CHIP_ID: + case BMP180: chip_info = &bmp180_chip_info; break; - case BMP280_CHIP_ID: + case BMP280: chip_info = &bmp280_chip_info; break; - case BME280_CHIP_ID: + case BME280: chip_info = &bme280_chip_info; break; - case BMP380_CHIP_ID: + case BMP380: chip_info = &bmp380_chip_info; break; default: @@ -1751,9 +1756,9 @@ int bmp280_common_probe(struct device *dev, ret = regmap_read(regmap, data->chip_info->id_reg, &chip_id); if (ret < 0) return ret; - if (chip_id != chip) { + if (chip_id != data->chip_info->chip_id) { dev_err(dev, "bad chip id: expected %x got %x\n", - chip, chip_id); + data->chip_info->chip_id, chip_id); return -EINVAL; } diff --git a/drivers/iio/pressure/bmp280-i2c.c b/drivers/iio/pressure/bmp280-i2c.c index 14eab086d24a..59921e8cd592 100644 --- a/drivers/iio/pressure/bmp280-i2c.c +++ b/drivers/iio/pressure/bmp280-i2c.c @@ -12,14 +12,14 @@ static int bmp280_i2c_probe(struct i2c_client *client) const struct i2c_device_id *id = i2c_client_get_device_id(client); switch (id->driver_data) { - case BMP180_CHIP_ID: + case BMP180: regmap_config = &bmp180_regmap_config; break; - case BMP280_CHIP_ID: - case BME280_CHIP_ID: + case BMP280: + case BME280: regmap_config = &bmp280_regmap_config; break; - case BMP380_CHIP_ID: + case BMP380: regmap_config = &bmp380_regmap_config; break; default: @@ -40,21 +40,21 @@ static int bmp280_i2c_probe(struct i2c_client *client) } static const struct of_device_id bmp280_of_i2c_match[] = { - { .compatible = "bosch,bmp085", .data = (void *)BMP180_CHIP_ID }, - { .compatible = "bosch,bmp180", .data = (void *)BMP180_CHIP_ID }, - { .compatible = "bosch,bmp280", .data = (void *)BMP280_CHIP_ID }, - { .compatible = "bosch,bme280", .data = (void *)BME280_CHIP_ID }, - { .compatible = "bosch,bmp380", .data = (void *)BMP380_CHIP_ID }, + { .compatible = "bosch,bmp085", .data = (void *)BMP180 }, + { .compatible = "bosch,bmp180", .data = (void *)BMP180 }, + { .compatible = "bosch,bmp280", .data = (void *)BMP280 }, + { .compatible = "bosch,bme280", .data = (void *)BME280 }, + { .compatible = "bosch,bmp380", .data = (void *)BMP380 }, { }, }; MODULE_DEVICE_TABLE(of, bmp280_of_i2c_match); static const struct i2c_device_id bmp280_i2c_id[] = { - {"bmp085", BMP180_CHIP_ID }, - {"bmp180", BMP180_CHIP_ID }, - {"bmp280", BMP280_CHIP_ID }, - {"bme280", BME280_CHIP_ID }, - {"bmp380", BMP380_CHIP_ID }, + {"bmp085", BMP180 }, + {"bmp180", BMP180 }, + {"bmp280", BMP280 }, + {"bme280", BME280 }, + {"bmp380", BMP380 }, { }, }; MODULE_DEVICE_TABLE(i2c, bmp280_i2c_id); diff --git a/drivers/iio/pressure/bmp280-spi.c b/drivers/iio/pressure/bmp280-spi.c index 011c68e07ebf..4a2df5b5d838 100644 --- a/drivers/iio/pressure/bmp280-spi.c +++ b/drivers/iio/pressure/bmp280-spi.c @@ -59,14 +59,14 @@ static int bmp280_spi_probe(struct spi_device *spi) } switch (id->driver_data) { - case BMP180_CHIP_ID: + case BMP180: regmap_config = &bmp180_regmap_config; break; - case BMP280_CHIP_ID: - case BME280_CHIP_ID: + case BMP280: + case BME280: regmap_config = &bmp280_regmap_config; break; - case BMP380_CHIP_ID: + case BMP380: regmap_config = &bmp380_regmap_config; break; default: @@ -101,11 +101,11 @@ static const struct of_device_id bmp280_of_spi_match[] = { MODULE_DEVICE_TABLE(of, bmp280_of_spi_match); static const struct spi_device_id bmp280_spi_id[] = { - { "bmp180", BMP180_CHIP_ID }, - { "bmp181", BMP180_CHIP_ID }, - { "bmp280", BMP280_CHIP_ID }, - { "bme280", BME280_CHIP_ID }, - { "bmp380", BMP380_CHIP_ID }, + { "bmp180", BMP180 }, + { "bmp181", BMP180 }, + { "bmp280", BMP280 }, + { "bme280", BME280 }, + { "bmp380", BMP380 }, { } }; MODULE_DEVICE_TABLE(spi, bmp280_spi_id); diff --git a/drivers/iio/pressure/bmp280.h b/drivers/iio/pressure/bmp280.h index c791325c7416..efc31bc84708 100644 --- a/drivers/iio/pressure/bmp280.h +++ b/drivers/iio/pressure/bmp280.h @@ -191,6 +191,14 @@ #define BMP280_PRESS_SKIPPED 0x80000 #define BMP280_HUMIDITY_SKIPPED 0x8000 +/* Enum with supported pressure sensor models */ +enum bmp280_variant { + BMP180, + BMP280, + BME280, + BMP380, +}; + /* Regmap configurations */ extern const struct regmap_config bmp180_regmap_config; extern const struct regmap_config bmp280_regmap_config; From patchwork Sun Dec 25 16:57: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: 13081510 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 7D815C3DA7A for ; Sun, 25 Dec 2022 16:57:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229749AbiLYQ5p (ORCPT ); Sun, 25 Dec 2022 11:57:45 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41902 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229960AbiLYQ5o (ORCPT ); Sun, 25 Dec 2022 11:57:44 -0500 Received: from mail-wm1-x334.google.com (mail-wm1-x334.google.com [IPv6:2a00:1450:4864:20::334]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 72FC626CC; Sun, 25 Dec 2022 08:57:43 -0800 (PST) Received: by mail-wm1-x334.google.com with SMTP id b24-20020a05600c4a9800b003d21efdd61dso6474391wmp.3; Sun, 25 Dec 2022 08:57:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=I+RDFj6BpHhJ2bFeylBpDtFtMyr1ovdocCHUnTCQ0GU=; b=OSW8iD6WXPGvrQcrcNlE8p0s0EDbg4nn1UNBqG0fOPZqiPtLdFkIodXaJGdImqr1d0 rrUhBQkKBOAS+PKD+1v5GrM9d6RD1VT/KIxqW/XhYnuGTh7e7/P4Q0l37oEri5s3RIOD tjCW/6taMRV+dSfECCKRLsPHolKcpWivufnnMNs88EJMXKJLzinf8LCHSw+5+47KMVCs n+MnjWXv/ktKg/AE7B7lalZTYCgDqhKXlE5zOSvsJzdCOtXbTrbRkhas9ELSRtxLKV1R s5ezJEL+z6EX+Ac9gg35ekzuVRrJtpa67koBvDa4Er+DBupLGugUYzv0obp2QWN3xgxr hFhg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=I+RDFj6BpHhJ2bFeylBpDtFtMyr1ovdocCHUnTCQ0GU=; b=MsLe6sw/fFUYG8grlqFyqFZLT/9SO7F/UWxKxP6tz2BRde92iI7/1DGnDZaEnx8Uww t75BIgxI6O3stPMhMu8FDdETPUB4dFNosBXF4tUYo0Mq0OmDf6TlwmfJkgKtn9uLQlCQ R1GF+lh+FdbFCyGdkEXdkhuyZOCPVjUi1GANZgi+8o8cJeAOOHsWyOl7Bx3C5qHU8IX3 6+un1Mx/0Q9DcXFW5IlowhsG3puRqgD3XIvLpE6yrxFVzdnwaWYKf3nVEJTCkIfgo7en PKun5DDOnk5PjSr56fjDWtpOsMXuChd7pcZnjIMlLQCS5rCZ0ZwPvauWnfCF9HxlhgK4 IHkQ== X-Gm-Message-State: AFqh2kqmrQdH/SrDvC3b1FMlcR9b+9FgGJOl9/gMUq3FZujBQa2XFiv2 dVB+I06VSlfG2AkIwSSe8g4rfx0DSkw= X-Google-Smtp-Source: AMrXdXuSTG+HJ0QJ16TOi/V7iahI/zTXvm945PzwqPqMJkk0YVJiGn9Nz0gdY/xzUODBJ6L/F8Pcrg== X-Received: by 2002:a05:600c:4920:b0:3d3:39a9:e659 with SMTP id f32-20020a05600c492000b003d339a9e659mr12174659wmp.21.1671987461917; Sun, 25 Dec 2022 08:57:41 -0800 (PST) Received: from localhost.localdomain (188.red-83-35-57.dynamicip.rima-tde.net. [83.35.57.188]) by smtp.gmail.com with ESMTPSA id n9-20020a05600c4f8900b003d1b4d957aasm12610058wmq.36.2022.12.25.08.57.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 25 Dec 2022 08:57:41 -0800 (PST) From: Angel Iglesias To: linux-iio@vger.kernel.org Cc: Angel Iglesias , Jonathan Cameron , Lars-Peter Clausen , "Rafael J. Wysocki" , Ulf Hansson , Paul Cercueil , linux-kernel@vger.kernel.org Subject: [PATCH 2/5] iio: pressure: bmp280: Add preinit callback Date: Sun, 25 Dec 2022 17:57:06 +0100 Message-Id: <724e92e64e6d91d48d762e804b430c716679bccb.1671986815.git.ang.iglesiasg@gmail.com> X-Mailer: git-send-email 2.39.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Adds preinit callback to execute operations on probe before applying initial configuration. Signed-off-by: Angel Iglesias diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c index 46959a91408f..c37cf2caec68 100644 --- a/drivers/iio/pressure/bmp280-core.c +++ b/drivers/iio/pressure/bmp280-core.c @@ -217,6 +217,7 @@ struct bmp280_chip_info { int (*read_press)(struct bmp280_data *, int *, int *); int (*read_humid)(struct bmp280_data *, int *, int *); int (*read_calib)(struct bmp280_data *); + int (*preinit)(struct bmp280_data *); }; /* @@ -935,6 +936,7 @@ static const struct bmp280_chip_info bmp280_chip_info = { .read_temp = bmp280_read_temp, .read_press = bmp280_read_press, .read_calib = bmp280_read_calib, + .preinit = NULL, }; static int bme280_chip_config(struct bmp280_data *data) @@ -979,6 +981,7 @@ static const struct bmp280_chip_info bme280_chip_info = { .read_press = bmp280_read_press, .read_humid = bmp280_read_humid, .read_calib = bme280_read_calib, + .preinit = NULL, }; /* @@ -1220,6 +1223,12 @@ static const int bmp380_odr_table[][2] = { [BMP380_ODR_0_0015HZ] = {0, 1526}, }; +static int bmp380_preinit(struct bmp280_data *data) +{ + /* BMP3xx requires soft-reset as part of initialization */ + return bmp380_cmd(data, BMP380_CMD_SOFT_RESET); +} + static int bmp380_chip_config(struct bmp280_data *data) { bool change = false, aux; @@ -1349,6 +1358,7 @@ static const struct bmp280_chip_info bmp380_chip_info = { .read_temp = bmp380_read_temp, .read_press = bmp380_read_press, .read_calib = bmp380_read_calib, + .preinit = bmp380_preinit, }; static int bmp180_measure(struct bmp280_data *data, u8 ctrl_meas) @@ -1604,6 +1614,7 @@ static const struct bmp280_chip_info bmp180_chip_info = { .read_temp = bmp180_read_temp, .read_press = bmp180_read_press, .read_calib = bmp180_read_calib, + .preinit = NULL, }; static irqreturn_t bmp085_eoc_irq(int irq, void *d) @@ -1762,9 +1773,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); + /* + * Some chips like the BMP3xx have preinit tasks to run + * before applying the initial configuration. + */ + if (data->chip_info->preinit) { + ret = data->chip_info->preinit(data); + dev_err(dev, "error running preinit tasks"); if (ret < 0) return ret; } From patchwork Sun Dec 25 16:58:00 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angel Iglesias X-Patchwork-Id: 13081511 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 5312CC3DA7A for ; Sun, 25 Dec 2022 16:58:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231329AbiLYQ6q (ORCPT ); Sun, 25 Dec 2022 11:58:46 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42580 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231312AbiLYQ6p (ORCPT ); Sun, 25 Dec 2022 11:58:45 -0500 Received: from mail-wm1-x32f.google.com (mail-wm1-x32f.google.com [IPv6:2a00:1450:4864:20::32f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 292662708; Sun, 25 Dec 2022 08:58:43 -0800 (PST) Received: by mail-wm1-x32f.google.com with SMTP id bi26-20020a05600c3d9a00b003d3404a89faso6990744wmb.1; Sun, 25 Dec 2022 08:58:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=h7OOtV+QVbdxLe2zaY1Y8skumo3pXeAcCWn4UwsrYSU=; b=k9oxVF/bSpJsOU+AaRxSnPM/xjAyu4p/qojemeUpd+EJQaPobEcG7aNSxhz8utG5BB 63sCbaj6JgHHt7kvfrOzGIHjoWkiMCdG/iGJ/ZliyQK+D1lgPCBKMnzhgYeasF1/Zlde zMjnjxTvbp9lUCrg5HdOF8n/NOMxVNQAj7Jne2yI4sytO1do0NkOYhYps4JIoofVayNN 4JAoV490Gg/erNA1lgEttt3ZJmbOk+XwAGLmymy19DwcJ/RjM7lfXd3SJi932LGi3VBB H7Hi4UMh5oXDGx5ykowfULCTWV5eLzUpSiNrkA5VpjX9sP2LQyJUw24awUmeOC7cSK1a lQVw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=h7OOtV+QVbdxLe2zaY1Y8skumo3pXeAcCWn4UwsrYSU=; b=hZnf4ObRm34X85TKcWuWYn6FV2+w6LSHOOYIEsgUc1xQ6fYtUEFWaQbjoZYA9rm3Uj HgafXm9fFe5KMLIjvSV+Rdjkgu1UEuiB1gSnwPUMh0pmsOO0fnXxwG2XA1CJH7q57G6q P/1AKUZYtIJd2K0CsdnKTUh9gEizInpPeqXyaj0oE50z6K2o2NZHcDFErQvZpdKqjfmL jTZ4iNPGQ8OTcY5zVOaIVgHVsik9GMDCIm56Tt1UT9v8Y0V5+bUfTc82oSPpdjkFS92c MTlDiI5lABVNkKUhhXdbQ/dqlFIGNgQBIX8jdhWINL6EETtIWGpMw7L3Tk7dPh9WZNa8 /afw== X-Gm-Message-State: AFqh2kpNEz2CH0QzZ28+Btl3+/HPMBC9CK3i740NeNW0QrGeQgPn8dve +Dzr8/XbkEWczh6qc4ngvo/37KS+RVY= X-Google-Smtp-Source: AMrXdXvsg/rN+q9bc8EnUBMY2RX6WRlxL2/ybZaW8rPlnsknVwZdk5BDKDte4NmMLwW2sl/dE7S8cA== X-Received: by 2002:a05:600c:4fcf:b0:3d1:d396:1ade with SMTP id o15-20020a05600c4fcf00b003d1d3961ademr11491503wmq.9.1671987521327; Sun, 25 Dec 2022 08:58:41 -0800 (PST) Received: from localhost.localdomain (188.red-83-35-57.dynamicip.rima-tde.net. [83.35.57.188]) by smtp.gmail.com with ESMTPSA id l7-20020a05600c4f0700b003d96c811d6dsm9965244wmq.30.2022.12.25.08.58.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 25 Dec 2022 08:58:41 -0800 (PST) From: Angel Iglesias To: linux-iio@vger.kernel.org Cc: Angel Iglesias , Jonathan Cameron , Lars-Peter Clausen , Nikita Yushchenko , Andy Shevchenko , Ulf Hansson , "Rafael J. Wysocki" , Paul Cercueil , linux-kernel@vger.kernel.org Subject: [PATCH 3/5] iio: pressure: bmp280: Add support for new sensor BMP580 Date: Sun, 25 Dec 2022 17:58:00 +0100 Message-Id: <5a1c9341102fdce2f49d151f0cba76f1ba9ba279.1671986815.git.ang.iglesiasg@gmail.com> X-Mailer: git-send-email 2.39.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Adds compatibility with the new sensor generation, the BMP580. The measurement and initialization codepaths are adapted from the device datasheet and the repository from manufacturer at https://github.com/boschsensortec/BMP5-Sensor-API. Signed-off-by: Angel Iglesias diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig index c9453389e4f7..1c18e3b2c501 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/BMP380 pressure sensor I2C driver" + tristate "Bosch Sensortec BMP180/BMP280/BMP380/BMP580 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, BMP280 and - BMP380 pressure and temperature sensors. Also supports the BME280 with + Say yes here to build support for Bosch Sensortec BMP180, BMP280, BMP380 + and BMP580 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 diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c index c37cf2caec68..005dbaf18607 100644 --- a/drivers/iio/pressure/bmp280-core.c +++ b/drivers/iio/pressure/bmp280-core.c @@ -13,6 +13,7 @@ * https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmp280-ds001.pdf * https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bme280-ds002.pdf * https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmp388-ds001.pdf + * https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmp581-ds004.pdf * * Notice: * The link to the bmp180 datasheet points to an outdated version missing these changes: @@ -130,6 +131,41 @@ enum bmp380_odr { BMP380_ODR_0_0015HZ, }; +enum bmp580_odr { + BMP580_ODR_240HZ, + BMP580_ODR_218HZ, + BMP580_ODR_199HZ, + BMP580_ODR_179HZ, + BMP580_ODR_160HZ, + BMP580_ODR_149HZ, + BMP580_ODR_140HZ, + BMP580_ODR_129HZ, + BMP580_ODR_120HZ, + BMP580_ODR_110HZ, + BMP580_ODR_100HZ, + BMP580_ODR_89HZ, + BMP580_ODR_80HZ, + BMP580_ODR_70HZ, + BMP580_ODR_60HZ, + BMP580_ODR_50HZ, + BMP580_ODR_45HZ, + BMP580_ODR_40HZ, + BMP580_ODR_35HZ, + BMP580_ODR_30HZ, + BMP580_ODR_25HZ, + BMP580_ODR_20HZ, + BMP580_ODR_15HZ, + BMP580_ODR_10HZ, + BMP580_ODR_5HZ, + BMP580_ODR_4HZ, + BMP580_ODR_3HZ, + BMP580_ODR_2HZ, + BMP580_ODR_1HZ, + BMP580_ODR_0_5HZ, + BMP580_ODR_0_25HZ, + BMP580_ODR_0_125HZ, +}; + struct bmp280_data { struct device *dev; struct mutex lock; @@ -1361,6 +1397,399 @@ static const struct bmp280_chip_info bmp380_chip_info = { .preinit = bmp380_preinit, }; +enum bmp580_commands { + BMP580_SOFT_RESET_CMD, + BMP580_NVM_WRITE_CMD, + BMP580_NVM_READ_CMD, + BMP580_EXT_MODE_CMD, +}; + +/* + * Helper function to send a command to BMP5XX sensors. + * + * BMP5xx sensors have a series of commands actionable + * writing specific sequences on the CMD register: + * SOFT_RESET: performs a reset of the system. + * NVM_READ: read the contents of a user position of the nvm memory. + * NVM_WRITE: write new data to a user position of the nvm memory. + * EXT_MODE: enable extended mode with additional debug pages. + */ +static int bmp580_cmd(struct bmp280_data *data, enum bmp580_commands cmd) +{ + unsigned long deadline; + unsigned int reg; + int ret; + + switch (cmd) { + case BMP580_SOFT_RESET_CMD: + /* Send reset word */ + ret = regmap_write(data->regmap, BMP580_REG_CMD, BMP580_CMD_SOFT_RESET); + if (ret) { + dev_err(data->dev, "failed to send reset command to device\n"); + return ret; + } + /* Wait 2ms for reset completion */ + usleep_range(2000, 2500); + /* Dummy read of chip_id */ + ret = regmap_read(data->regmap, BMP580_REG_CHIP_ID, ®); + if (ret) { + dev_err(data->dev, "failed to reestablish comms after reset\n"); + return ret; + } + /* Check if POR bit is set on interrupt reg */ + ret = regmap_read(data->regmap, BMP580_REG_INT_STATUS, ®); + if (ret) { + dev_err(data->dev, "error reading interrupt status register\n"); + return ret; + } + if (!(reg & BMP580_INT_STATUS_POR_MASK)) { + dev_err(data->dev, "error resetting sensor\n"); + return -EINVAL; + } + break; + case BMP580_NVM_WRITE_CMD: + case BMP580_NVM_READ_CMD: + /* Check nvm ready flag */ + ret = regmap_read(data->regmap, BMP580_REG_STATUS, ®); + if (ret) { + dev_err(data->dev, "failed to check nvm status\n"); + return ret; + } + if (!(reg & BMP580_STATUS_NVM_RDY_MASK)) { + dev_err(data->dev, "sensor's nvm is not ready\n"); + return -EIO; + } + /* Send NVM operation sequence */ + ret = regmap_write(data->regmap, BMP580_REG_CMD, BMP580_CMD_NVM_OP_SEQ_0); + if (ret) { + dev_err(data->dev, "failed to send nvm operation's first sequence\n"); + return ret; + } + if (cmd == BMP580_NVM_WRITE_CMD) { + /* Send write sequence */ + ret = regmap_write(data->regmap, BMP580_REG_CMD, + BMP580_CMD_NVM_WRITE_SEQ_1); + if (ret) { + dev_err(data->dev, "failed to send nvm write sequence\n"); + return ret; + } + /* Datasheet says on 4.8.1.2 it takes approximately 10ms */ + usleep_range(10000, 10500); + deadline = jiffies + msecs_to_jiffies(10); + } else { + /* Send read sequence */ + ret = regmap_write(data->regmap, BMP580_REG_CMD, + BMP580_CMD_NVM_READ_SEQ_1); + if (ret) { + dev_err(data->dev, "failed to send nvm read sequence\n"); + return ret; + } + /* Datasheet says on 4.8.1.1 it takes approximately 200us */ + usleep_range(200, 250); + deadline = jiffies + usecs_to_jiffies(200); + } + if (ret) { + dev_err(data->dev, "failed to write command sequence\n"); + return -EIO; + } + /* Wait until NVM is ready again */ + do { + ret = regmap_read(data->regmap, BMP580_REG_STATUS, ®); + if (ret) { + dev_err(data->dev, "failed to check nvm status\n"); + reg &= ~BMP580_STATUS_NVM_RDY_MASK; + } + } while (time_before(jiffies, deadline) && !(reg & BMP580_STATUS_NVM_RDY_MASK)); + + if (!(reg & BMP580_STATUS_NVM_RDY_MASK)) { + dev_err(data->dev, + "reached timeout waiting for nvm operation completion\n"); + return -ETIMEDOUT; + } + /* Checks nvm error flags */ + if ((reg & BMP580_STATUS_NVM_ERR_MASK) || (reg & BMP580_STATUS_NVM_CMD_ERR_MASK)) { + dev_err(data->dev, "error processing nvm operation\n"); + return -EIO; + } + break; + case BMP580_EXT_MODE_CMD: + ret = regmap_write(data->regmap, BMP580_REG_CMD, BMP580_CMD_EXTMODE_SEQ_0); + if (ret) { + dev_err(data->dev, "failed to send ext_mode first sequence\n"); + return ret; + } + ret = regmap_write(data->regmap, BMP580_REG_CMD, BMP580_CMD_EXTMODE_SEQ_1); + if (ret) { + dev_err(data->dev, "failed to send ext_mode second sequence\n"); + return ret; + } + ret = regmap_write(data->regmap, BMP580_REG_CMD, BMP580_CMD_EXTMODE_SEQ_2); + if (ret) { + dev_err(data->dev, "failed to send ext_mode second sequence\n"); + return ret; + } + break; + } + + return 0; +} + +/* + * Contrary to previous sensors families, compensation algorithm is builtin. + * We are only required to read the register raw data and adapt the ranges + * for what is expected on IIO ABI. + */ + +static int bmp580_read_temp(struct bmp280_data *data, int *val) +{ + s32 raw_temp; + int ret; + + ret = regmap_bulk_read(data->regmap, BMP580_REG_TEMP_XLSB, data->buf, + sizeof(data->buf)); + if (ret) { + dev_err(data->dev, "failed to read temperature\n"); + return ret; + } + + raw_temp = get_unaligned_le24(data->buf); + if (raw_temp == BMP580_TEMP_SKIPPED) { + dev_err(data->dev, "reading temperature skipped\n"); + return -EIO; + } + + /* + * Temperature is returned in Celsius degrees in fractional + * form down 2^16. We reescale by x1000 to return milli Celsius + * to respect IIO ABI. + */ + *val = (raw_temp * 1000) >> 16; + return IIO_VAL_INT; +} + +static int bmp580_read_press(struct bmp280_data *data, int *val, int *val2) +{ + u32 raw_press; + int ret; + + ret = regmap_bulk_read(data->regmap, BMP580_REG_PRESS_XLSB, data->buf, + sizeof(data->buf)); + if (ret) { + dev_err(data->dev, "failed to read pressure\n"); + return ret; + } + + raw_press = get_unaligned_le24(data->buf); + if (raw_press == BMP580_PRESS_SKIPPED) { + dev_err(data->dev, "reading pressure skipped\n"); + return -EIO; + } + /* + * Pressure is returned in Pascals in fractional form down 2^16. + * We reescale /1000 to convert to kilopascal to respect IIO ABI. + */ + *val = raw_press; + *val2 = 64000; // 2^6 * 1000 + return IIO_VAL_FRACTIONAL; +} + +static const int bmp580_odr_table[][2] = { + [BMP580_ODR_240HZ] = {240, 0}, + [BMP580_ODR_218HZ] = {218, 0}, + [BMP580_ODR_199HZ] = {199, 0}, + [BMP580_ODR_179HZ] = {179, 0}, + [BMP580_ODR_160HZ] = {160, 0}, + [BMP580_ODR_149HZ] = {149, 0}, + [BMP580_ODR_140HZ] = {140, 0}, + [BMP580_ODR_129HZ] = {129, 0}, + [BMP580_ODR_120HZ] = {120, 0}, + [BMP580_ODR_110HZ] = {110, 0}, + [BMP580_ODR_100HZ] = {100, 0}, + [BMP580_ODR_89HZ] = {89, 0}, + [BMP580_ODR_80HZ] = {80, 0}, + [BMP580_ODR_70HZ] = {70, 0}, + [BMP580_ODR_60HZ] = {60, 0}, + [BMP580_ODR_50HZ] = {50, 0}, + [BMP580_ODR_45HZ] = {45, 0}, + [BMP580_ODR_40HZ] = {40, 0}, + [BMP580_ODR_35HZ] = {35, 0}, + [BMP580_ODR_30HZ] = {30, 0}, + [BMP580_ODR_25HZ] = {25, 0}, + [BMP580_ODR_20HZ] = {20, 0}, + [BMP580_ODR_15HZ] = {15, 0}, + [BMP580_ODR_10HZ] = {10, 0}, + [BMP580_ODR_5HZ] = {5, 0}, + [BMP580_ODR_4HZ] = {4, 0}, + [BMP580_ODR_3HZ] = {3, 0}, + [BMP580_ODR_2HZ] = {2, 0}, + [BMP580_ODR_1HZ] = {1, 0}, + [BMP580_ODR_0_5HZ] = {0, 500000}, + [BMP580_ODR_0_25HZ] = {0, 250000}, + [BMP580_ODR_0_125HZ] = {0, 125000}, +}; + +static int bmp580_preinit(struct bmp280_data *data) +{ + unsigned int reg; + int ret; + + /* Issue soft-reset command */ + ret = bmp580_cmd(data, BMP580_SOFT_RESET_CMD); + if (ret) + return ret; + /* Post powerup sequence */ + ret = regmap_read(data->regmap, BMP580_REG_CHIP_ID, ®); + if (ret) + return ret; + if (reg != BMP580_CHIP_ID) { + dev_err(data->dev, "preinit: unexpected chip_id\n"); + return ret; + } + ret = regmap_read(data->regmap, BMP580_REG_STATUS, ®); + if (ret) + return ret; + /* Check nvm status */ + if (!(reg & BMP580_STATUS_NVM_RDY_MASK) || (reg & BMP580_STATUS_NVM_ERR_MASK)) { + dev_err(data->dev, "preinit: nvm error on powerup sequence\n"); + return ret; + } + + return 0; +} + +static int bmp580_chip_config(struct bmp280_data *data) +{ + bool change = false, aux; + unsigned int tmp; + u8 reg_val; + int ret; + + /* Sets sensor in standby mode */ + ret = regmap_update_bits(data->regmap, BMP580_REG_ODR_CONFIG, + BMP580_MODE_MASK | BMP580_ODR_DEEPSLEEP_DIS, + BMP580_ODR_DEEPSLEEP_DIS | + FIELD_PREP(BMP580_MODE_MASK, BMP580_MODE_SLEEP)); + if (ret) { + dev_err(data->dev, "failed to change sensor to standby mode\n"); + return ret; + } + /* From datasheet's table 4: electrical characteristics */ + usleep_range(2500, 3000); + + /* Set default DSP mode settings */ + reg_val = FIELD_PREP(BMP580_DSP_COMP_MASK, BMP580_DSP_PRESS_TEMP_COMP_EN) | + BMP580_DSP_SHDW_IIR_TEMP_EN | BMP580_DSP_SHDW_IIR_PRESS_EN; + + ret = regmap_update_bits(data->regmap, BMP580_REG_DSP_CONFIG, + BMP580_DSP_COMP_MASK | + BMP580_DSP_SHDW_IIR_TEMP_EN | + BMP580_DSP_SHDW_IIR_PRESS_EN, reg_val); + + /* Configure oversampling */ + reg_val = FIELD_PREP(BMP580_OSR_TEMP_MASK, data->oversampling_temp) | + FIELD_PREP(BMP580_OSR_PRESS_MASK, data->oversampling_press) | + BMP580_OSR_PRESS_EN; + + ret = regmap_update_bits_check(data->regmap, BMP580_REG_OSR_CONFIG, + BMP580_OSR_TEMP_MASK | BMP580_OSR_PRESS_MASK | + BMP580_OSR_PRESS_EN, + reg_val, &aux); + if (ret) { + dev_err(data->dev, "failed to write oversampling register\n"); + return ret; + } + change = change || aux; + + /* Configure output data rate */ + ret = regmap_update_bits_check(data->regmap, BMP580_REG_ODR_CONFIG, BMP580_ODR_MASK, + FIELD_PREP(BMP580_ODR_MASK, data->sampling_freq), + &aux); + if (ret) { + dev_err(data->dev, "failed to write ODR configuration register\n"); + return ret; + } + change = change || aux; + + /* Set filter data */ + reg_val = FIELD_PREP(BMP580_DSP_IIR_PRESS_MASK, data->iir_filter_coeff) | + FIELD_PREP(BMP580_DSP_IIR_TEMP_MASK, data->iir_filter_coeff); + + ret = regmap_update_bits_check(data->regmap, BMP580_REG_DSP_IIR, + BMP580_DSP_IIR_PRESS_MASK | + BMP580_DSP_IIR_TEMP_MASK, + reg_val, &aux); + if (ret) { + dev_err(data->dev, "failed to write config register\n"); + return ret; + } + change = change || aux; + + /* Restore sensor to normal operation mode */ + ret = regmap_write_bits(data->regmap, BMP580_REG_ODR_CONFIG, + BMP580_MODE_MASK, + FIELD_PREP(BMP580_MODE_MASK, BMP580_MODE_NORMAL)); + if (ret) { + dev_err(data->dev, "failed to set normal mode\n"); + return ret; + } + /* From datasheet's table 4: electrical characteristics */ + usleep_range(3000, 3500); + + if (change) { + /* + * Check if ODR and OSR settings are valid or we are + * operating in a degraded mode. + */ + ret = regmap_read(data->regmap, BMP580_REG_EFF_OSR, &tmp); + if (ret) { + dev_err(data->dev, "error reading effective OSR register\n"); + return ret; + } + if (!(tmp & BMP580_EFF_OSR_VALID_ODR)) { + dev_warn(data->dev, "OSR and ODR incompatible settings detected\n"); + /* Set current OSR settings from data on effective OSR */ + data->oversampling_temp = FIELD_GET(BMP580_EFF_OSR_TEMP_MASK, tmp); + data->oversampling_press = FIELD_GET(BMP580_EFF_OSR_PRESS_MASK, tmp); + return -EINVAL; + } + } + + return 0; +} + +static const int bmp580_oversampling_avail[] = { 1, 2, 4, 8, 16, 32, 64, 128 }; +static const int bmp580_iir_filter_coeffs_avail[] = { 1, 2, 4, 8, 16, 32, 64, 128 }; + +static const struct bmp280_chip_info bmp580_chip_info = { + .id_reg = BMP580_REG_CHIP_ID, + .chip_id = BMP580_CHIP_ID, + .start_up_time = 2000, + .channels = bmp380_channels, + .num_channels = 2, + + .oversampling_temp_avail = bmp580_oversampling_avail, + .num_oversampling_temp_avail = ARRAY_SIZE(bmp580_oversampling_avail), + .oversampling_temp_default = ilog2(1), + + .oversampling_press_avail = bmp580_oversampling_avail, + .num_oversampling_press_avail = ARRAY_SIZE(bmp580_oversampling_avail), + .oversampling_press_default = ilog2(4), + + .sampling_freq_avail = bmp580_odr_table, + .num_sampling_freq_avail = ARRAY_SIZE(bmp580_odr_table) * 2, + .sampling_freq_default = BMP580_ODR_50HZ, + + .iir_filter_coeffs_avail = bmp580_iir_filter_coeffs_avail, + .num_iir_filter_coeffs_avail = ARRAY_SIZE(bmp580_iir_filter_coeffs_avail), + .iir_filter_coeff_default = 2, + + .chip_config = bmp580_chip_config, + .read_temp = bmp580_read_temp, + .read_press = bmp580_read_press, + .read_calib = NULL, + .preinit = bmp580_preinit, +}; + static int bmp180_measure(struct bmp280_data *data, u8 ctrl_meas) { const int conversion_time_max[] = { 4500, 7500, 13500, 25500 }; @@ -1713,6 +2142,9 @@ int bmp280_common_probe(struct device *dev, case BMP380: chip_info = &bmp380_chip_info; break; + case BMP580: + chip_info = &bmp580_chip_info; + break; default: return -EINVAL; } @@ -1779,9 +2211,10 @@ int bmp280_common_probe(struct device *dev, */ if (data->chip_info->preinit) { ret = data->chip_info->preinit(data); - dev_err(dev, "error running preinit tasks"); - if (ret < 0) + if (ret) { + dev_err(dev, "error running preinit tasks\n"); return ret; + } } ret = data->chip_info->chip_config(data); @@ -1795,11 +2228,12 @@ 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. */ - - ret = data->chip_info->read_calib(data); - if (ret < 0) - return dev_err_probe(data->dev, ret, - "failed to read calibration coefficients\n"); + if (data->chip_info->read_calib) { + ret = data->chip_info->read_calib(data); + 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 diff --git a/drivers/iio/pressure/bmp280-i2c.c b/drivers/iio/pressure/bmp280-i2c.c index 59921e8cd592..c52d2b477bb7 100644 --- a/drivers/iio/pressure/bmp280-i2c.c +++ b/drivers/iio/pressure/bmp280-i2c.c @@ -22,6 +22,9 @@ static int bmp280_i2c_probe(struct i2c_client *client) case BMP380: regmap_config = &bmp380_regmap_config; break; + case BMP580: + regmap_config = &bmp580_regmap_config; + break; default: return -EINVAL; } @@ -45,6 +48,7 @@ static const struct of_device_id bmp280_of_i2c_match[] = { { .compatible = "bosch,bmp280", .data = (void *)BMP280 }, { .compatible = "bosch,bme280", .data = (void *)BME280 }, { .compatible = "bosch,bmp380", .data = (void *)BMP380 }, + { .compatible = "bosch,bmp580", .data = (void *)BMP580 }, { }, }; MODULE_DEVICE_TABLE(of, bmp280_of_i2c_match); @@ -55,6 +59,7 @@ static const struct i2c_device_id bmp280_i2c_id[] = { {"bmp280", BMP280 }, {"bme280", BME280 }, {"bmp380", BMP380 }, + {"bmp580", BMP580 }, { }, }; MODULE_DEVICE_TABLE(i2c, bmp280_i2c_id); diff --git a/drivers/iio/pressure/bmp280-regmap.c b/drivers/iio/pressure/bmp280-regmap.c index c98c67970265..3ee56720428c 100644 --- a/drivers/iio/pressure/bmp280-regmap.c +++ b/drivers/iio/pressure/bmp280-regmap.c @@ -115,6 +115,54 @@ static bool bmp380_is_volatile_reg(struct device *dev, unsigned int reg) } } +static bool bmp580_is_writeable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case BMP580_REG_NVM_DATA_MSB: + case BMP580_REG_NVM_DATA_LSB: + case BMP580_REG_NVM_ADDR: + case BMP580_REG_ODR_CONFIG: + case BMP580_REG_OSR_CONFIG: + case BMP580_REG_INT_SOURCE: + case BMP580_REG_INT_CONFIG: + case BMP580_REG_OOR_THR_MSB: + case BMP580_REG_OOR_THR_LSB: + case BMP580_REG_OOR_CONFIG: + case BMP580_REG_OOR_RANGE: + case BMP580_REG_IF_CONFIG: + case BMP580_REG_FIFO_CONFIG: + case BMP580_REG_FIFO_SEL: + case BMP580_REG_DSP_CONFIG: + case BMP580_REG_DSP_IIR: + case BMP580_REG_CMD: + return true; + default: + return false; + } +} + +static bool bmp580_is_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case BMP580_REG_NVM_DATA_MSB: + case BMP580_REG_NVM_DATA_LSB: + case BMP580_REG_FIFO_COUNT: + case BMP580_REG_INT_STATUS: + case BMP580_REG_PRESS_XLSB: + case BMP580_REG_PRESS_LSB: + case BMP580_REG_PRESS_MSB: + case BMP580_REG_FIFO_DATA: + case BMP580_REG_TEMP_XLSB: + case BMP580_REG_TEMP_LSB: + case BMP580_REG_TEMP_MSB: + case BMP580_REG_EFF_OSR: + case BMP580_REG_STATUS: + return true; + default: + return false; + } +} + const struct regmap_config bmp280_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -138,3 +186,15 @@ const struct regmap_config bmp380_regmap_config = { .volatile_reg = bmp380_is_volatile_reg, }; EXPORT_SYMBOL_NS(bmp380_regmap_config, IIO_BMP280); + +const struct regmap_config bmp580_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = BMP580_REG_CMD, + .cache_type = REGCACHE_RBTREE, + + .writeable_reg = bmp580_is_writeable_reg, + .volatile_reg = bmp580_is_volatile_reg, +}; +EXPORT_SYMBOL_NS(bmp580_regmap_config, IIO_BMP280); diff --git a/drivers/iio/pressure/bmp280-spi.c b/drivers/iio/pressure/bmp280-spi.c index 4a2df5b5d838..5653c3c33081 100644 --- a/drivers/iio/pressure/bmp280-spi.c +++ b/drivers/iio/pressure/bmp280-spi.c @@ -69,6 +69,9 @@ static int bmp280_spi_probe(struct spi_device *spi) case BMP380: regmap_config = &bmp380_regmap_config; break; + case BMP580: + regmap_config = &bmp580_regmap_config; + break; default: return -EINVAL; } @@ -96,6 +99,7 @@ static const struct of_device_id bmp280_of_spi_match[] = { { .compatible = "bosch,bmp280", }, { .compatible = "bosch,bme280", }, { .compatible = "bosch,bmp380", }, + { .compatible = "bosch,bmp580", }, { }, }; MODULE_DEVICE_TABLE(of, bmp280_of_spi_match); @@ -106,6 +110,7 @@ static const struct spi_device_id bmp280_spi_id[] = { { "bmp280", BMP280 }, { "bme280", BME280 }, { "bmp380", BMP380 }, + { "bmp580", BMP580 }, { } }; MODULE_DEVICE_TABLE(spi, bmp280_spi_id); diff --git a/drivers/iio/pressure/bmp280.h b/drivers/iio/pressure/bmp280.h index efc31bc84708..27d2abc17d01 100644 --- a/drivers/iio/pressure/bmp280.h +++ b/drivers/iio/pressure/bmp280.h @@ -3,6 +3,107 @@ #include #include +/* BMP580 specific registers */ +#define BMP580_REG_CMD 0x7E +#define BMP580_REG_EFF_OSR 0x38 +#define BMP580_REG_ODR_CONFIG 0x37 +#define BMP580_REG_OSR_CONFIG 0x36 +#define BMP580_REG_IF_CONFIG 0x13 +#define BMP580_REG_REV_ID 0x02 +#define BMP580_REG_CHIP_ID 0x01 +/* OOR allows to configure a pressure alarm */ +#define BMP580_REG_OOR_CONFIG 0x35 +#define BMP580_REG_OOR_RANGE 0x34 +#define BMP580_REG_OOR_THR_MSB 0x33 +#define BMP580_REG_OOR_THR_LSB 0x32 +/* DSP registers (IIR filters) */ +#define BMP580_REG_DSP_IIR 0x31 +#define BMP580_REG_DSP_CONFIG 0x30 +/* NVM access registers */ +#define BMP580_REG_NVM_DATA_MSB 0x2D +#define BMP580_REG_NVM_DATA_LSB 0x2C +#define BMP580_REG_NVM_ADDR 0x2B +/* Status registers */ +#define BMP580_REG_STATUS 0x28 +#define BMP580_REG_INT_STATUS 0x27 +#define BMP580_REG_CHIP_STATUS 0x11 +/* Data registers */ +#define BMP580_REG_FIFO_DATA 0x29 +#define BMP580_REG_PRESS_MSB 0x22 +#define BMP580_REG_PRESS_LSB 0x21 +#define BMP580_REG_PRESS_XLSB 0x20 +#define BMP580_REG_TEMP_MSB 0x1F +#define BMP580_REG_TEMP_LSB 0x1E +#define BMP580_REG_TEMP_XLSB 0x1D +/* FIFO config registers */ +#define BMP580_REG_FIFO_SEL 0x18 +#define BMP580_REG_FIFO_COUNT 0x17 +#define BMP580_REG_FIFO_CONFIG 0x16 +/* Interruptions config registers */ +#define BMP580_REG_INT_SOURCE 0x15 +#define BMP580_REG_INT_CONFIG 0x14 + +#define BMP580_CMD_NOOP 0x00 +#define BMP580_CMD_EXTMODE_SEQ_0 0x73 +#define BMP580_CMD_EXTMODE_SEQ_1 0xB4 +#define BMP580_CMD_EXTMODE_SEQ_2 0x69 +#define BMP580_CMD_NVM_OP_SEQ_0 0x5D +#define BMP580_CMD_NVM_READ_SEQ_1 0xA5 +#define BMP580_CMD_NVM_WRITE_SEQ_1 0xA0 +#define BMP580_CMD_SOFT_RESET 0xB6 + +#define BMP580_INT_STATUS_POR_MASK BIT(4) + +#define BMP580_STATUS_CORE_RDY_MASK BIT(0) +#define BMP580_STATUS_NVM_RDY_MASK BIT(1) +#define BMP580_STATUS_NVM_ERR_MASK BIT(2) +#define BMP580_STATUS_NVM_CMD_ERR_MASK BIT(3) + +#define BMP580_OSR_PRESS_MASK GENMASK(5, 3) +#define BMP580_OSR_TEMP_MASK GENMASK(2, 0) +#define BMP580_OSR_PRESS_EN BIT(6) +#define BMP580_EFF_OSR_PRESS_MASK GENMASK(5, 3) +#define BMP580_EFF_OSR_TEMP_MASK GENMASK(2, 0) +#define BMP580_EFF_OSR_VALID_ODR BIT(7) + +#define BMP580_ODR_MASK GENMASK(6, 2) +#define BMP580_MODE_MASK GENMASK(1, 0) +#define BMP580_MODE_SLEEP 0 +#define BMP580_MODE_NORMAL 1 +#define BMP580_MODE_FORCED 2 +#define BMP580_MODE_CONTINOUS 3 +#define BMP580_ODR_DEEPSLEEP_DIS BIT(7) + +#define BMP580_DSP_COMP_MASK GENMASK(1, 0) +#define BMP580_DSP_COMP_DIS 0 +#define BMP580_DSP_TEMP_COMP_EN 1 +/* + * In section 7.27 of datasheet, modes 2 and 3 are technically the same. + * Pressure compensation means also enabling temperature compensation + */ +#define BMP580_DSP_PRESS_COMP_EN 2 +#define BMP580_DSP_PRESS_TEMP_COMP_EN 3 +#define BMP580_DSP_IIR_FORCED_FLUSH BIT(2) +#define BMP580_DSP_SHDW_IIR_TEMP_EN BIT(3) +#define BMP580_DSP_FIFO_IIR_TEMP_EN BIT(4) +#define BMP580_DSP_SHDW_IIR_PRESS_EN BIT(5) +#define BMP580_DSP_FIFO_IIR_PRESS_EN BIT(6) +#define BMP580_DSP_OOR_IIR_PRESS_EN BIT(7) + +#define BMP580_DSP_IIR_PRESS_MASK GENMASK(5, 3) +#define BMP580_DSP_IIR_TEMP_MASK GENMASK(2, 0) +#define BMP580_FILTER_OFF 0 +#define BMP580_FILTER_1X 1 +#define BMP580_FILTER_3X 2 +#define BMP580_FILTER_7X 3 +#define BMP580_FILTER_15X 4 +#define BMP580_FILTER_31X 5 +#define BMP580_FILTER_63X 6 +#define BMP580_FILTER_127X 7 + +#define BMP580_TEMP_SKIPPED 0x7f7f7f +#define BMP580_PRESS_SKIPPED 0x7f7f7f + /* BMP380 specific registers */ #define BMP380_REG_CMD 0x7E #define BMP380_REG_CONFIG 0x1F @@ -180,6 +281,7 @@ #define BMP280_REG_RESET 0xE0 #define BMP280_REG_ID 0xD0 +#define BMP580_CHIP_ID 0x50 #define BMP380_CHIP_ID 0x50 #define BMP180_CHIP_ID 0x55 #define BMP280_CHIP_ID 0x58 @@ -197,12 +299,14 @@ enum bmp280_variant { BMP280, BME280, BMP380, + BMP580, }; /* 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; +extern const struct regmap_config bmp580_regmap_config; /* Probe called from different transports */ int bmp280_common_probe(struct device *dev, From patchwork Sun Dec 25 16:59:21 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angel Iglesias X-Patchwork-Id: 13081512 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 1BD8BC3DA7A for ; Sun, 25 Dec 2022 17:00:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231428AbiLYRAA (ORCPT ); Sun, 25 Dec 2022 12:00:00 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42968 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231404AbiLYQ77 (ORCPT ); Sun, 25 Dec 2022 11:59:59 -0500 Received: from mail-wm1-x330.google.com (mail-wm1-x330.google.com [IPv6:2a00:1450:4864:20::330]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0D07938BE; Sun, 25 Dec 2022 08:59:58 -0800 (PST) Received: by mail-wm1-x330.google.com with SMTP id o15so6511245wmr.4; Sun, 25 Dec 2022 08:59:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=W7Uxgqg5mAtgEreFJVlyY9FG6dh29sWzofDPJcOPslk=; b=W+z5fHTW0GWZfXeF5Fz+zx0jp9fjQpYyWv/sgsDVZguqzeap9vHyRDwo8Pd3tg6PHk O0Gyr/CHU/wSZJYlL5ASoF2XVE370spCTn7F5hxACWF4dMnLNxew9n/Q2ZEv0mjNm6Hf 6bDTzqaQd3Kp64PYuMNdhjg/sTFuHHENKsP6YS5HO+v20avYKx1rQTrk/nxPJSE7kdUH P35nPj+Eprgyl+f0bwnG99lXoiy6hh8ffynJbLXuQVgz/Se1eRm9Z2m83yhF+mFT9/Ok 7duSnv4dibiRHVZjNvAWURAd97D3uIelrZlUwR1aTnDq5uhuqQilq7VLqf7zj8DcYofN VSrA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=W7Uxgqg5mAtgEreFJVlyY9FG6dh29sWzofDPJcOPslk=; b=VpPa6lzJzk6ZDcEG7dvLZVka/e+gSW/YjzB8zi1JaXrOiLGGkQ+GcTp0KFSUaFHnhm ASck7QiPHV0zPPerhPyzzhyAMjlJDKmtuGRfm/a6BCWFtIU7YiaJ3JyxQ5f2Ui8Vpqfr vzTaSCv45l1ITlh6zAvHJT3zfQrKUponZ64LNlk+zq41FjB1bBRAZhOm9iJdYexder09 seWVL9pEUWs/KlLTxNPiD/9ho5usq5MiAIPHq+9X+JLrZaV8f/iKhxVx05O9VwNA86tB 9xCi11uJ6gq+ED8dd1yEmgGRzaImiZdpj2wwQPsDnmg0kVuLoEQqQ+8wr+y7yAhLbr8J xDOg== X-Gm-Message-State: AFqh2kqFjItVa5oL1pn5etsSs9R8IJsygIEHW5YIWU6dZ8iP1xuqcrEJ VeXqKUrWK+bSzQUCodWSX5hkX3jzA+o= X-Google-Smtp-Source: AMrXdXuT2E457V230n2bDHOPYEK+CtL4Z9J9GgfherN++wEWxFmuDoWgzzapKU7pA2H3QSlks2mPTw== X-Received: by 2002:a1c:7c0f:0:b0:3d5:816e:2fb2 with SMTP id x15-20020a1c7c0f000000b003d5816e2fb2mr12060163wmc.14.1671987596475; Sun, 25 Dec 2022 08:59:56 -0800 (PST) Received: from localhost.localdomain (188.red-83-35-57.dynamicip.rima-tde.net. [83.35.57.188]) by smtp.gmail.com with ESMTPSA id l42-20020a05600c1d2a00b003d23928b654sm17734371wms.11.2022.12.25.08.59.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 25 Dec 2022 08:59:56 -0800 (PST) From: Angel Iglesias To: linux-iio@vger.kernel.org Cc: Angel Iglesias , Jonathan Cameron , Lars-Peter Clausen , Rob Herring , Krzysztof Kozlowski , Andreas Klinger , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 4/5] dt-bindings: iio: pressure: bmp085: Add BMP580 compatible string Date: Sun, 25 Dec 2022 17:59:21 +0100 Message-Id: <778a9d07ad1d88e036cc1ddd9c3fa53390b906a3.1671986815.git.ang.iglesiasg@gmail.com> X-Mailer: git-send-email 2.39.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Add bosch,bmp580 to compatible string for the new family of sensors. This family includes the BMP580 and BMP581 sensors. The register map in this family presents significant departures from previous generations. Signed-off-by: Angel Iglesias Acked-by: Krzysztof Kozlowski diff --git a/Documentation/devicetree/bindings/iio/pressure/bmp085.yaml b/Documentation/devicetree/bindings/iio/pressure/bmp085.yaml index 72cd2c2d3f17..f52c4794e21b 100644 --- a/Documentation/devicetree/bindings/iio/pressure/bmp085.yaml +++ b/Documentation/devicetree/bindings/iio/pressure/bmp085.yaml @@ -17,6 +17,7 @@ description: | 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 + https://www.bosch-sensortec.com/bst/products/all_products/bmp580 properties: compatible: @@ -26,6 +27,7 @@ properties: - bosch,bmp280 - bosch,bme280 - bosch,bmp380 + - bosch,bmp580 reg: maxItems: 1 From patchwork Sun Dec 25 17:00:53 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angel Iglesias X-Patchwork-Id: 13081513 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 0DEB1C3DA7A for ; Sun, 25 Dec 2022 17:01:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229810AbiLYRBc (ORCPT ); Sun, 25 Dec 2022 12:01:32 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44200 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231230AbiLYRBa (ORCPT ); Sun, 25 Dec 2022 12:01:30 -0500 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 B923F2675; Sun, 25 Dec 2022 09:01:28 -0800 (PST) Received: by mail-wm1-x32d.google.com with SMTP id p13-20020a05600c468d00b003cf8859ed1bso6489533wmo.1; Sun, 25 Dec 2022 09:01:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Cba7a4CNg3T6ktAC4rnAyxADOxp4yPgdrX7lNI9dXpg=; b=H0Aj/Vinm/zwqMAF2JdMoqdNwUcHXNSZjxw25hpLmoeQGxLZI7rhyg8fk0QBLTcJYY mhF6/2ucKw07Yr2DZfM/rhjEMG5/43flkqnOFoERH2L96XanqNyYJKepIbnkeaD3Ka7w SubIsAasXZO5nNE1TplUqh1R3/ESoKEjY5AQHJAvM1wDD5HwkMK7NcYLPO7p4MeJUvkh owE1G92lGsAMkFtAdTB63cc9dh9y5xlVzoaCtZk8WycsKUGODr1cvElxx3BX31vQkI6q lBT4InUeoVf4s+fXggMZaDHCanExMhRcx1fvLgmrsmLG9iKRb8v79wxlBSCy7qXu5cjb tWlQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Cba7a4CNg3T6ktAC4rnAyxADOxp4yPgdrX7lNI9dXpg=; b=nnr4PlGcu1w6ll0EUz3rQCV2AdOpdUsKDj6FqFhT+f8seQJK0BraJWasrLujvYAKsM T1TNHx2qMhwxU7OyCoAmORigkExn6KHVkuHIxoVONDwVZTXI92lJzsmLkzI0Agl05/VM uIt0WsI/06AN00xqn/iBTpUG7a2JyW3Smi3pgZggcXF6PknsLQ8CVkECuYbJANAUcyLL L5UaNqh676/nLnVzgWSJd3yknHAuQFSZYSvTNcxcSVZ2HerV2QRJWD82T9UcF7PnEAwG 1IoYE6EzJDYDNRK9GkLWqlgYGrMJxyWLNoyHIYh7ZKeTa9KBI3h4AxeS+0zeQ+Aqjvcf srEg== X-Gm-Message-State: AFqh2kpv4+FD3/8my4Y2HtytgyJwaVyvroxxO7dwjQ3noacBdzh5LRiI iAtwdHTe/Ekdl608A0HUdIWNVoF2aP0= X-Google-Smtp-Source: AMrXdXsQlRHT5tu3MNUAE/vWmOJHVJFZx1mw+qmYgPECdDHia48mL8hq6+j4kxauC+pBVCx5LIUrwg== X-Received: by 2002:a05:600c:5008:b0:3cf:6f4d:c25d with SMTP id n8-20020a05600c500800b003cf6f4dc25dmr11618497wmr.21.1671987687086; Sun, 25 Dec 2022 09:01:27 -0800 (PST) Received: from localhost.localdomain (188.red-83-35-57.dynamicip.rima-tde.net. [83.35.57.188]) by smtp.gmail.com with ESMTPSA id k2-20020a05600c1c8200b003d974076f13sm5812308wms.3.2022.12.25.09.01.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 25 Dec 2022 09:01:26 -0800 (PST) From: Angel Iglesias To: linux-iio@vger.kernel.org Cc: Angel Iglesias , Jonathan Cameron , Lars-Peter Clausen , Paul Cercueil , "Rafael J. Wysocki" , Ulf Hansson , linux-kernel@vger.kernel.org Subject: [PATCH 5/5] iio: pressure: bmp280: Add nvmem operations for BMP580 Date: Sun, 25 Dec 2022 18:00:53 +0100 Message-Id: X-Mailer: git-send-email 2.39.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org The pressure sensor BMP580 contains a non-volatile memory that stores trimming and configuration params. That memory provides an programmable user range of three 2-byte words. Signed-off-by: Angel Iglesias diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c index 005dbaf18607..4e0d89a71eab 100644 --- a/drivers/iio/pressure/bmp280-core.c +++ b/drivers/iio/pressure/bmp280-core.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -1628,8 +1629,140 @@ static const int bmp580_odr_table[][2] = { [BMP580_ODR_0_125HZ] = {0, 125000}, }; +const int bmp580_nvmem_addrs[] = { 0x20, 0x21, 0x22 }; + +static int bmp580_nvmem_read(void *priv, unsigned int offset, void *val, + size_t bytes) +{ + struct bmp280_data *data = priv; + u16 *dst = val; + int ret, addr; + + pm_runtime_get_sync(data->dev); + mutex_lock(&data->lock); + + /* Set sensor in standby mode */ + ret = regmap_update_bits(data->regmap, BMP580_REG_ODR_CONFIG, + BMP580_MODE_MASK | BMP580_ODR_DEEPSLEEP_DIS, + BMP580_ODR_DEEPSLEEP_DIS | + FIELD_PREP(BMP580_MODE_MASK, BMP580_MODE_SLEEP)); + if (ret) { + dev_err(data->dev, "failed to change sensor to standby mode\n"); + return ret; + } + /* Wait standby transition time */ + usleep_range(2500, 3000); + + while (bytes >= sizeof(u16)) { + addr = bmp580_nvmem_addrs[offset / sizeof(u16)]; + + ret = regmap_write(data->regmap, BMP580_REG_NVM_ADDR, + FIELD_PREP(BMP580_NVM_ROW_ADDR_MASK, addr)); + if (ret) { + dev_err(data->dev, "error writing nvm address\n"); + goto exit; + } + + ret = bmp580_cmd(data, BMP580_NVM_READ_CMD); + if (ret) + goto exit; + + ret = regmap_bulk_read(data->regmap, BMP580_REG_NVM_DATA_LSB, &data->le16, + sizeof(data->le16)); + if (ret) { + dev_err(data->dev, "error reading nvm data regs\n"); + goto exit; + } + + *dst++ = le16_to_cpu(data->le16); + bytes -= sizeof(u16); + offset += sizeof(u16); + } +exit: + /* Restore chip config */ + data->chip_info->chip_config(data); + mutex_unlock(&data->lock); + pm_runtime_mark_last_busy(data->dev); + pm_runtime_put_autosuspend(data->dev); + return ret; +} + +static int bmp580_nvmem_write(void *priv, unsigned int offset, void *val, + size_t bytes) +{ + struct bmp280_data *data = priv; + u16 *buf = val; + int ret, addr; + + pm_runtime_get_sync(data->dev); + mutex_lock(&data->lock); + + /* Set sensor in standby mode */ + ret = regmap_update_bits(data->regmap, BMP580_REG_ODR_CONFIG, + BMP580_MODE_MASK | BMP580_ODR_DEEPSLEEP_DIS, + BMP580_ODR_DEEPSLEEP_DIS | + FIELD_PREP(BMP580_MODE_MASK, BMP580_MODE_SLEEP)); + if (ret) { + dev_err(data->dev, "failed to change sensor to standby mode\n"); + return ret; + } + /* Wait standby transition time */ + usleep_range(2500, 3000); + + while (bytes >= sizeof(u16)) { + addr = bmp580_nvmem_addrs[offset / sizeof(u16)]; + + ret = regmap_write(data->regmap, BMP580_REG_NVM_ADDR, BMP580_NVM_PROG_EN | + FIELD_PREP(BMP580_NVM_ROW_ADDR_MASK, addr)); + if (ret) { + dev_err(data->dev, "error writing nvm address\n"); + goto exit; + } + data->le16 = cpu_to_le16(*buf++); + + ret = regmap_bulk_write(data->regmap, BMP580_REG_NVM_DATA_LSB, &data->le16, + sizeof(data->le16)); + if (ret) { + dev_err(data->dev, "error writing LSB NVM data regs\n"); + goto exit; + } + + ret = bmp580_cmd(data, BMP580_NVM_WRITE_CMD); + if (ret) + goto exit; + + /* Disable programming mode bit */ + ret = regmap_update_bits(data->regmap, BMP580_REG_NVM_ADDR, + BMP580_NVM_PROG_EN, 0); + if (ret) { + dev_err(data->dev, "error resetting nvm write\n"); + goto exit; + } + + bytes -= sizeof(u16); + offset += sizeof(u16); + } +exit: + /* Restore chip config */ + data->chip_info->chip_config(data); + mutex_unlock(&data->lock); + pm_runtime_mark_last_busy(data->dev); + pm_runtime_put_autosuspend(data->dev); + return ret; +} + static int bmp580_preinit(struct bmp280_data *data) { + struct nvmem_config config = { + .dev = data->dev, + .priv = data, + .name = "bmp580_nvmem", + .word_size = sizeof(u16), + .stride = sizeof(u16), + .size = 3 * sizeof(u16), + .reg_read = bmp580_nvmem_read, + .reg_write = bmp580_nvmem_write, + }; unsigned int reg; int ret; @@ -1653,8 +1786,8 @@ static int bmp580_preinit(struct bmp280_data *data) dev_err(data->dev, "preinit: nvm error on powerup sequence\n"); return ret; } - - return 0; + /* Register nvmem device */ + return PTR_ERR_OR_ZERO(devm_nvmem_register(config.dev, &config)); } static int bmp580_chip_config(struct bmp280_data *data) diff --git a/drivers/iio/pressure/bmp280.h b/drivers/iio/pressure/bmp280.h index 27d2abc17d01..e2a093a4f767 100644 --- a/drivers/iio/pressure/bmp280.h +++ b/drivers/iio/pressure/bmp280.h @@ -101,6 +101,9 @@ #define BMP580_FILTER_63X 6 #define BMP580_FILTER_127X 7 +#define BMP580_NVM_ROW_ADDR_MASK GENMASK(5, 0) +#define BMP580_NVM_PROG_EN BIT(6) + #define BMP580_TEMP_SKIPPED 0x7f7f7f #define BMP580_PRESS_SKIPPED 0x7f7f7f