1// SPDX-License-Identifier: GPL-2.0
2/*
3 * BME680 - SPI Driver
4 *
5 * Copyright (C) 2018 Himanshu Jha <himanshujha199640@gmail.com>
6 */
7#include <linux/mod_devicetable.h>
8#include <linux/module.h>
9#include <linux/regmap.h>
10#include <linux/spi/spi.h>
11
12#include "bme680.h"
13
14struct bme680_spi_bus_context {
15	struct spi_device *spi;
16	u8 current_page;
17};
18
19/*
20 * In SPI mode there are only 7 address bits, a "page" register determines
21 * which part of the 8-bit range is active. This function looks at the address
22 * and writes the page selection bit if needed
23 */
24static int bme680_regmap_spi_select_page(
25	struct bme680_spi_bus_context *ctx, u8 reg)
26{
27	struct spi_device *spi = ctx->spi;
28	int ret;
29	u8 buf[2];
30	u8 page = (reg & 0x80) ? 0 : 1; /* Page "1" is low range */
31
32	if (page == ctx->current_page)
33		return 0;
34
35	/*
36	 * Data sheet claims we're only allowed to change bit 4, so we must do
37	 * a read-modify-write on each and every page select
38	 */
39	buf[0] = BME680_REG_STATUS;
40	ret = spi_write_then_read(spi, buf, 1, buf + 1, 1);
41	if (ret < 0) {
42		dev_err(&spi->dev, "failed to set page %u\n", page);
43		return ret;
44	}
45
46	buf[0] = BME680_REG_STATUS;
47	if (page)
48		buf[1] |= BME680_SPI_MEM_PAGE_BIT;
49	else
50		buf[1] &= ~BME680_SPI_MEM_PAGE_BIT;
51
52	ret = spi_write(spi, buf, 2);
53	if (ret < 0) {
54		dev_err(&spi->dev, "failed to set page %u\n", page);
55		return ret;
56	}
57
58	ctx->current_page = page;
59
60	return 0;
61}
62
63static int bme680_regmap_spi_write(void *context, const void *data,
64				   size_t count)
65{
66	struct bme680_spi_bus_context *ctx = context;
67	struct spi_device *spi = ctx->spi;
68	int ret;
69	u8 buf[2];
70
71	memcpy(buf, data, 2);
72
73	ret = bme680_regmap_spi_select_page(ctx, buf[0]);
74	if (ret)
75		return ret;
76
77	/*
78	 * The SPI register address (= full register address without bit 7)
79	 * and the write command (bit7 = RW = '0')
80	 */
81	buf[0] &= ~0x80;
82
83	return spi_write(spi, buf, 2);
84}
85
86static int bme680_regmap_spi_read(void *context, const void *reg,
87				  size_t reg_size, void *val, size_t val_size)
88{
89	struct bme680_spi_bus_context *ctx = context;
90	struct spi_device *spi = ctx->spi;
91	int ret;
92	u8 addr = *(const u8 *)reg;
93
94	ret = bme680_regmap_spi_select_page(ctx, addr);
95	if (ret)
96		return ret;
97
98	addr |= 0x80; /* bit7 = RW = '1' */
99
100	return spi_write_then_read(spi, &addr, 1, val, val_size);
101}
102
103static struct regmap_bus bme680_regmap_bus = {
104	.write = bme680_regmap_spi_write,
105	.read = bme680_regmap_spi_read,
106	.reg_format_endian_default = REGMAP_ENDIAN_BIG,
107	.val_format_endian_default = REGMAP_ENDIAN_BIG,
108};
109
110static int bme680_spi_probe(struct spi_device *spi)
111{
112	const struct spi_device_id *id = spi_get_device_id(spi);
113	struct bme680_spi_bus_context *bus_context;
114	struct regmap *regmap;
115	int ret;
116
117	spi->bits_per_word = 8;
118	ret = spi_setup(spi);
119	if (ret < 0) {
120		dev_err(&spi->dev, "spi_setup failed!\n");
121		return ret;
122	}
123
124	bus_context = devm_kzalloc(&spi->dev, sizeof(*bus_context), GFP_KERNEL);
125	if (!bus_context)
126		return -ENOMEM;
127
128	bus_context->spi = spi;
129	bus_context->current_page = 0xff; /* Undefined on warm boot */
130
131	regmap = devm_regmap_init(&spi->dev, &bme680_regmap_bus,
132				  bus_context, &bme680_regmap_config);
133	if (IS_ERR(regmap)) {
134		dev_err(&spi->dev, "Failed to register spi regmap %ld\n", PTR_ERR(regmap));
135		return PTR_ERR(regmap);
136	}
137
138	return bme680_core_probe(&spi->dev, regmap, id->name);
139}
140
141static const struct spi_device_id bme680_spi_id[] = {
142	{"bme680", 0},
143	{},
144};
145MODULE_DEVICE_TABLE(spi, bme680_spi_id);
146
147static const struct of_device_id bme680_of_spi_match[] = {
148	{ .compatible = "bosch,bme680", },
149	{},
150};
151MODULE_DEVICE_TABLE(of, bme680_of_spi_match);
152
153static struct spi_driver bme680_spi_driver = {
154	.driver = {
155		.name			= "bme680_spi",
156		.of_match_table		= bme680_of_spi_match,
157	},
158	.probe = bme680_spi_probe,
159	.id_table = bme680_spi_id,
160};
161module_spi_driver(bme680_spi_driver);
162
163MODULE_AUTHOR("Himanshu Jha <himanshujha199640@gmail.com>");
164MODULE_DESCRIPTION("Bosch BME680 SPI driver");
165MODULE_LICENSE("GPL v2");
166MODULE_IMPORT_NS(IIO_BME680);
167