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