167 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * BME680 - SPI Driver4 *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 determines21 * which part of the 8-bit range is active. This function looks at the address22 * and writes the page selection bit if needed23 */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 do37 * a read-modify-write on each and every page select38 */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 else50 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 const 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