162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * BME680 - SPI Driver
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2018 Himanshu Jha <himanshujha199640@gmail.com>
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci#include <linux/mod_devicetable.h>
862306a36Sopenharmony_ci#include <linux/module.h>
962306a36Sopenharmony_ci#include <linux/regmap.h>
1062306a36Sopenharmony_ci#include <linux/spi/spi.h>
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include "bme680.h"
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_cistruct bme680_spi_bus_context {
1562306a36Sopenharmony_ci	struct spi_device *spi;
1662306a36Sopenharmony_ci	u8 current_page;
1762306a36Sopenharmony_ci};
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci/*
2062306a36Sopenharmony_ci * In SPI mode there are only 7 address bits, a "page" register determines
2162306a36Sopenharmony_ci * which part of the 8-bit range is active. This function looks at the address
2262306a36Sopenharmony_ci * and writes the page selection bit if needed
2362306a36Sopenharmony_ci */
2462306a36Sopenharmony_cistatic int bme680_regmap_spi_select_page(
2562306a36Sopenharmony_ci	struct bme680_spi_bus_context *ctx, u8 reg)
2662306a36Sopenharmony_ci{
2762306a36Sopenharmony_ci	struct spi_device *spi = ctx->spi;
2862306a36Sopenharmony_ci	int ret;
2962306a36Sopenharmony_ci	u8 buf[2];
3062306a36Sopenharmony_ci	u8 page = (reg & 0x80) ? 0 : 1; /* Page "1" is low range */
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci	if (page == ctx->current_page)
3362306a36Sopenharmony_ci		return 0;
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	/*
3662306a36Sopenharmony_ci	 * Data sheet claims we're only allowed to change bit 4, so we must do
3762306a36Sopenharmony_ci	 * a read-modify-write on each and every page select
3862306a36Sopenharmony_ci	 */
3962306a36Sopenharmony_ci	buf[0] = BME680_REG_STATUS;
4062306a36Sopenharmony_ci	ret = spi_write_then_read(spi, buf, 1, buf + 1, 1);
4162306a36Sopenharmony_ci	if (ret < 0) {
4262306a36Sopenharmony_ci		dev_err(&spi->dev, "failed to set page %u\n", page);
4362306a36Sopenharmony_ci		return ret;
4462306a36Sopenharmony_ci	}
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	buf[0] = BME680_REG_STATUS;
4762306a36Sopenharmony_ci	if (page)
4862306a36Sopenharmony_ci		buf[1] |= BME680_SPI_MEM_PAGE_BIT;
4962306a36Sopenharmony_ci	else
5062306a36Sopenharmony_ci		buf[1] &= ~BME680_SPI_MEM_PAGE_BIT;
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	ret = spi_write(spi, buf, 2);
5362306a36Sopenharmony_ci	if (ret < 0) {
5462306a36Sopenharmony_ci		dev_err(&spi->dev, "failed to set page %u\n", page);
5562306a36Sopenharmony_ci		return ret;
5662306a36Sopenharmony_ci	}
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	ctx->current_page = page;
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	return 0;
6162306a36Sopenharmony_ci}
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_cistatic int bme680_regmap_spi_write(void *context, const void *data,
6462306a36Sopenharmony_ci				   size_t count)
6562306a36Sopenharmony_ci{
6662306a36Sopenharmony_ci	struct bme680_spi_bus_context *ctx = context;
6762306a36Sopenharmony_ci	struct spi_device *spi = ctx->spi;
6862306a36Sopenharmony_ci	int ret;
6962306a36Sopenharmony_ci	u8 buf[2];
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	memcpy(buf, data, 2);
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci	ret = bme680_regmap_spi_select_page(ctx, buf[0]);
7462306a36Sopenharmony_ci	if (ret)
7562306a36Sopenharmony_ci		return ret;
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	/*
7862306a36Sopenharmony_ci	 * The SPI register address (= full register address without bit 7)
7962306a36Sopenharmony_ci	 * and the write command (bit7 = RW = '0')
8062306a36Sopenharmony_ci	 */
8162306a36Sopenharmony_ci	buf[0] &= ~0x80;
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	return spi_write(spi, buf, 2);
8462306a36Sopenharmony_ci}
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_cistatic int bme680_regmap_spi_read(void *context, const void *reg,
8762306a36Sopenharmony_ci				  size_t reg_size, void *val, size_t val_size)
8862306a36Sopenharmony_ci{
8962306a36Sopenharmony_ci	struct bme680_spi_bus_context *ctx = context;
9062306a36Sopenharmony_ci	struct spi_device *spi = ctx->spi;
9162306a36Sopenharmony_ci	int ret;
9262306a36Sopenharmony_ci	u8 addr = *(const u8 *)reg;
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci	ret = bme680_regmap_spi_select_page(ctx, addr);
9562306a36Sopenharmony_ci	if (ret)
9662306a36Sopenharmony_ci		return ret;
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	addr |= 0x80; /* bit7 = RW = '1' */
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci	return spi_write_then_read(spi, &addr, 1, val, val_size);
10162306a36Sopenharmony_ci}
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_cistatic struct regmap_bus bme680_regmap_bus = {
10462306a36Sopenharmony_ci	.write = bme680_regmap_spi_write,
10562306a36Sopenharmony_ci	.read = bme680_regmap_spi_read,
10662306a36Sopenharmony_ci	.reg_format_endian_default = REGMAP_ENDIAN_BIG,
10762306a36Sopenharmony_ci	.val_format_endian_default = REGMAP_ENDIAN_BIG,
10862306a36Sopenharmony_ci};
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_cistatic int bme680_spi_probe(struct spi_device *spi)
11162306a36Sopenharmony_ci{
11262306a36Sopenharmony_ci	const struct spi_device_id *id = spi_get_device_id(spi);
11362306a36Sopenharmony_ci	struct bme680_spi_bus_context *bus_context;
11462306a36Sopenharmony_ci	struct regmap *regmap;
11562306a36Sopenharmony_ci	int ret;
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	spi->bits_per_word = 8;
11862306a36Sopenharmony_ci	ret = spi_setup(spi);
11962306a36Sopenharmony_ci	if (ret < 0) {
12062306a36Sopenharmony_ci		dev_err(&spi->dev, "spi_setup failed!\n");
12162306a36Sopenharmony_ci		return ret;
12262306a36Sopenharmony_ci	}
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	bus_context = devm_kzalloc(&spi->dev, sizeof(*bus_context), GFP_KERNEL);
12562306a36Sopenharmony_ci	if (!bus_context)
12662306a36Sopenharmony_ci		return -ENOMEM;
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci	bus_context->spi = spi;
12962306a36Sopenharmony_ci	bus_context->current_page = 0xff; /* Undefined on warm boot */
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci	regmap = devm_regmap_init(&spi->dev, &bme680_regmap_bus,
13262306a36Sopenharmony_ci				  bus_context, &bme680_regmap_config);
13362306a36Sopenharmony_ci	if (IS_ERR(regmap)) {
13462306a36Sopenharmony_ci		dev_err(&spi->dev, "Failed to register spi regmap %ld\n", PTR_ERR(regmap));
13562306a36Sopenharmony_ci		return PTR_ERR(regmap);
13662306a36Sopenharmony_ci	}
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	return bme680_core_probe(&spi->dev, regmap, id->name);
13962306a36Sopenharmony_ci}
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_cistatic const struct spi_device_id bme680_spi_id[] = {
14262306a36Sopenharmony_ci	{"bme680", 0},
14362306a36Sopenharmony_ci	{},
14462306a36Sopenharmony_ci};
14562306a36Sopenharmony_ciMODULE_DEVICE_TABLE(spi, bme680_spi_id);
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_cistatic const struct of_device_id bme680_of_spi_match[] = {
14862306a36Sopenharmony_ci	{ .compatible = "bosch,bme680", },
14962306a36Sopenharmony_ci	{},
15062306a36Sopenharmony_ci};
15162306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, bme680_of_spi_match);
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_cistatic struct spi_driver bme680_spi_driver = {
15462306a36Sopenharmony_ci	.driver = {
15562306a36Sopenharmony_ci		.name			= "bme680_spi",
15662306a36Sopenharmony_ci		.of_match_table		= bme680_of_spi_match,
15762306a36Sopenharmony_ci	},
15862306a36Sopenharmony_ci	.probe = bme680_spi_probe,
15962306a36Sopenharmony_ci	.id_table = bme680_spi_id,
16062306a36Sopenharmony_ci};
16162306a36Sopenharmony_cimodule_spi_driver(bme680_spi_driver);
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ciMODULE_AUTHOR("Himanshu Jha <himanshujha199640@gmail.com>");
16462306a36Sopenharmony_ciMODULE_DESCRIPTION("Bosch BME680 SPI driver");
16562306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
16662306a36Sopenharmony_ciMODULE_IMPORT_NS(IIO_BME680);
167