Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

iio: pressure: bmp280: Add nvmem operations for BMP580

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 <ang.iglesiasg@gmail.com>
Link: https://lore.kernel.org/r/f3f453d9b2c0f7820ca9c56e24e2165b6c39bb67.1676823250.git.ang.iglesiasg@gmail.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Angel Iglesias and committed by
Jonathan Cameron
accb9d05 43cce95c

+212 -1
+209 -1
drivers/iio/pressure/bmp280-core.c
··· 28 28 #include <linux/bitfield.h> 29 29 #include <linux/device.h> 30 30 #include <linux/module.h> 31 + #include <linux/nvmem-provider.h> 31 32 #include <linux/regmap.h> 32 33 #include <linux/delay.h> 33 34 #include <linux/iio/iio.h> ··· 1285 1284 return 0; 1286 1285 } 1287 1286 1287 + /** 1288 + * bmp580_nvm_operation() - Helper function to commit NVM memory operations 1289 + * @data: sensor data struct 1290 + * @is_write: flag to signal write operation 1291 + */ 1292 + static int bmp580_nvm_operation(struct bmp280_data *data, bool is_write) 1293 + { 1294 + unsigned long timeout, poll; 1295 + unsigned int reg; 1296 + int ret; 1297 + 1298 + /* Check NVM ready flag */ 1299 + ret = regmap_read(data->regmap, BMP580_REG_STATUS, &reg); 1300 + if (ret) { 1301 + dev_err(data->dev, "failed to check nvm status\n"); 1302 + return ret; 1303 + } 1304 + if (!(reg & BMP580_STATUS_NVM_RDY_MASK)) { 1305 + dev_err(data->dev, "sensor's nvm is not ready\n"); 1306 + return -EIO; 1307 + } 1308 + 1309 + /* Start NVM operation sequence */ 1310 + ret = regmap_write(data->regmap, BMP580_REG_CMD, BMP580_CMD_NVM_OP_SEQ_0); 1311 + if (ret) { 1312 + dev_err(data->dev, "failed to send nvm operation's first sequence\n"); 1313 + return ret; 1314 + } 1315 + if (is_write) { 1316 + /* Send NVM write sequence */ 1317 + ret = regmap_write(data->regmap, BMP580_REG_CMD, 1318 + BMP580_CMD_NVM_WRITE_SEQ_1); 1319 + if (ret) { 1320 + dev_err(data->dev, "failed to send nvm write sequence\n"); 1321 + return ret; 1322 + } 1323 + /* Datasheet says on 4.8.1.2 it takes approximately 10ms */ 1324 + poll = 2000; 1325 + timeout = 12000; 1326 + } else { 1327 + /* Send NVM read sequence */ 1328 + ret = regmap_write(data->regmap, BMP580_REG_CMD, 1329 + BMP580_CMD_NVM_READ_SEQ_1); 1330 + if (ret) { 1331 + dev_err(data->dev, "failed to send nvm read sequence\n"); 1332 + return ret; 1333 + } 1334 + /* Datasheet says on 4.8.1.1 it takes approximately 200us */ 1335 + poll = 50; 1336 + timeout = 400; 1337 + } 1338 + if (ret) { 1339 + dev_err(data->dev, "failed to write command sequence\n"); 1340 + return -EIO; 1341 + } 1342 + 1343 + /* Wait until NVM is ready again */ 1344 + ret = regmap_read_poll_timeout(data->regmap, BMP580_REG_STATUS, reg, 1345 + (reg & BMP580_STATUS_NVM_RDY_MASK), 1346 + poll, timeout); 1347 + if (ret) { 1348 + dev_err(data->dev, "error checking nvm operation status\n"); 1349 + return ret; 1350 + } 1351 + 1352 + /* Check NVM error flags */ 1353 + if ((reg & BMP580_STATUS_NVM_ERR_MASK) || (reg & BMP580_STATUS_NVM_CMD_ERR_MASK)) { 1354 + dev_err(data->dev, "error processing nvm operation\n"); 1355 + return -EIO; 1356 + } 1357 + 1358 + return 0; 1359 + } 1360 + 1288 1361 /* 1289 1362 * Contrary to previous sensors families, compensation algorithm is builtin. 1290 1363 * We are only required to read the register raw data and adapt the ranges ··· 1454 1379 [BMP580_ODR_0_125HZ] = {0, 125000}, 1455 1380 }; 1456 1381 1382 + static const int bmp580_nvmem_addrs[] = { 0x20, 0x21, 0x22 }; 1383 + 1384 + static int bmp580_nvmem_read(void *priv, unsigned int offset, void *val, 1385 + size_t bytes) 1386 + { 1387 + struct bmp280_data *data = priv; 1388 + u16 *dst = val; 1389 + int ret, addr; 1390 + 1391 + pm_runtime_get_sync(data->dev); 1392 + mutex_lock(&data->lock); 1393 + 1394 + /* Set sensor in standby mode */ 1395 + ret = regmap_update_bits(data->regmap, BMP580_REG_ODR_CONFIG, 1396 + BMP580_MODE_MASK | BMP580_ODR_DEEPSLEEP_DIS, 1397 + BMP580_ODR_DEEPSLEEP_DIS | 1398 + FIELD_PREP(BMP580_MODE_MASK, BMP580_MODE_SLEEP)); 1399 + if (ret) { 1400 + dev_err(data->dev, "failed to change sensor to standby mode\n"); 1401 + goto exit; 1402 + } 1403 + /* Wait standby transition time */ 1404 + usleep_range(2500, 3000); 1405 + 1406 + while (bytes >= sizeof(*dst)) { 1407 + addr = bmp580_nvmem_addrs[offset / sizeof(*dst)]; 1408 + 1409 + ret = regmap_write(data->regmap, BMP580_REG_NVM_ADDR, 1410 + FIELD_PREP(BMP580_NVM_ROW_ADDR_MASK, addr)); 1411 + if (ret) { 1412 + dev_err(data->dev, "error writing nvm address\n"); 1413 + goto exit; 1414 + } 1415 + 1416 + ret = bmp580_nvm_operation(data, false); 1417 + if (ret) 1418 + goto exit; 1419 + 1420 + ret = regmap_bulk_read(data->regmap, BMP580_REG_NVM_DATA_LSB, &data->le16, 1421 + sizeof(data->le16)); 1422 + if (ret) { 1423 + dev_err(data->dev, "error reading nvm data regs\n"); 1424 + goto exit; 1425 + } 1426 + 1427 + *dst++ = le16_to_cpu(data->le16); 1428 + bytes -= sizeof(*dst); 1429 + offset += sizeof(*dst); 1430 + } 1431 + exit: 1432 + /* Restore chip config */ 1433 + data->chip_info->chip_config(data); 1434 + mutex_unlock(&data->lock); 1435 + pm_runtime_mark_last_busy(data->dev); 1436 + pm_runtime_put_autosuspend(data->dev); 1437 + return ret; 1438 + } 1439 + 1440 + static int bmp580_nvmem_write(void *priv, unsigned int offset, void *val, 1441 + size_t bytes) 1442 + { 1443 + struct bmp280_data *data = priv; 1444 + u16 *buf = val; 1445 + int ret, addr; 1446 + 1447 + pm_runtime_get_sync(data->dev); 1448 + mutex_lock(&data->lock); 1449 + 1450 + /* Set sensor in standby mode */ 1451 + ret = regmap_update_bits(data->regmap, BMP580_REG_ODR_CONFIG, 1452 + BMP580_MODE_MASK | BMP580_ODR_DEEPSLEEP_DIS, 1453 + BMP580_ODR_DEEPSLEEP_DIS | 1454 + FIELD_PREP(BMP580_MODE_MASK, BMP580_MODE_SLEEP)); 1455 + if (ret) { 1456 + dev_err(data->dev, "failed to change sensor to standby mode\n"); 1457 + goto exit; 1458 + } 1459 + /* Wait standby transition time */ 1460 + usleep_range(2500, 3000); 1461 + 1462 + while (bytes >= sizeof(*buf)) { 1463 + addr = bmp580_nvmem_addrs[offset / sizeof(*buf)]; 1464 + 1465 + ret = regmap_write(data->regmap, BMP580_REG_NVM_ADDR, BMP580_NVM_PROG_EN | 1466 + FIELD_PREP(BMP580_NVM_ROW_ADDR_MASK, addr)); 1467 + if (ret) { 1468 + dev_err(data->dev, "error writing nvm address\n"); 1469 + goto exit; 1470 + } 1471 + data->le16 = cpu_to_le16(*buf++); 1472 + 1473 + ret = regmap_bulk_write(data->regmap, BMP580_REG_NVM_DATA_LSB, &data->le16, 1474 + sizeof(data->le16)); 1475 + if (ret) { 1476 + dev_err(data->dev, "error writing LSB NVM data regs\n"); 1477 + goto exit; 1478 + } 1479 + 1480 + ret = bmp580_nvm_operation(data, true); 1481 + if (ret) 1482 + goto exit; 1483 + 1484 + /* Disable programming mode bit */ 1485 + ret = regmap_update_bits(data->regmap, BMP580_REG_NVM_ADDR, 1486 + BMP580_NVM_PROG_EN, 0); 1487 + if (ret) { 1488 + dev_err(data->dev, "error resetting nvm write\n"); 1489 + goto exit; 1490 + } 1491 + 1492 + bytes -= sizeof(*buf); 1493 + offset += sizeof(*buf); 1494 + } 1495 + exit: 1496 + /* Restore chip config */ 1497 + data->chip_info->chip_config(data); 1498 + mutex_unlock(&data->lock); 1499 + pm_runtime_mark_last_busy(data->dev); 1500 + pm_runtime_put_autosuspend(data->dev); 1501 + return ret; 1502 + } 1503 + 1457 1504 static int bmp580_preinit(struct bmp280_data *data) 1458 1505 { 1506 + struct nvmem_config config = { 1507 + .dev = data->dev, 1508 + .priv = data, 1509 + .name = "bmp580_nvmem", 1510 + .word_size = sizeof(u16), 1511 + .stride = sizeof(u16), 1512 + .size = 3 * sizeof(u16), 1513 + .reg_read = bmp580_nvmem_read, 1514 + .reg_write = bmp580_nvmem_write, 1515 + }; 1459 1516 unsigned int reg; 1460 1517 int ret; 1461 1518 ··· 1615 1408 return -EIO; 1616 1409 } 1617 1410 1618 - return 0; 1411 + /* Register nvmem device */ 1412 + return PTR_ERR_OR_ZERO(devm_nvmem_register(config.dev, &config)); 1619 1413 } 1620 1414 1621 1415 static int bmp580_chip_config(struct bmp280_data *data)
+3
drivers/iio/pressure/bmp280.h
··· 104 104 #define BMP580_FILTER_63X 6 105 105 #define BMP580_FILTER_127X 7 106 106 107 + #define BMP580_NVM_ROW_ADDR_MASK GENMASK(5, 0) 108 + #define BMP580_NVM_PROG_EN BIT(6) 109 + 107 110 #define BMP580_TEMP_SKIPPED 0x7f7f7f 108 111 #define BMP580_PRESS_SKIPPED 0x7f7f7f 109 112