File Index
Files and directories
Sign in
FILE

smi330_i2c.c

File preview with syntax highlighting.

linux-6.19.14/drivers/iio/imu/smi330/smi330_i2c.c C
  1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
  2/*
  3 * Copyright (c) 2025 Robert Bosch GmbH.
  4 */
  5#include <linux/i2c.h>
  6#include <linux/mod_devicetable.h>
  7#include <linux/module.h>
  8#include <linux/regmap.h>
  9
 10#include "smi330.h"
 11
 12#define SMI330_NUM_DUMMY_BYTES 2
 13#define SMI330_I2C_MAX_RX_BUFFER_SIZE \
 14	(SMI330_NUM_DUMMY_BYTES + SMI330_SCAN_LEN * sizeof(s16))
 15
 16struct smi330_i2c_priv {
 17	struct i2c_client *i2c;
 18	u8 rx_buffer[SMI330_I2C_MAX_RX_BUFFER_SIZE];
 19};
 20
 21static int smi330_regmap_i2c_read(void *context, const void *reg_buf,
 22				  size_t reg_size, void *val_buf,
 23				  size_t val_size)
 24{
 25	struct smi330_i2c_priv *priv = context;
 26	int ret;
 27
 28	if (SMI330_NUM_DUMMY_BYTES + val_size > SMI330_I2C_MAX_RX_BUFFER_SIZE)
 29		return -EINVAL;
 30
 31	/*
 32	 * SMI330 I2C read frame:
 33	 * <Slave address[6:0], RnW> <x, Register address[6:0]>
 34	 * <Slave address[6:0], RnW> <Dummy[7:0]> <Dummy[7:0]> <Data_0[7:0]> <Data_1[15:8]>...
 35	 *                                                     <Data_N[7:0]> <Data_N[15:8]>
 36	 * Remark: Slave address is not considered part of the frame in the following definitions
 37	 */
 38	struct i2c_msg msgs[] = {
 39		{
 40			.addr = priv->i2c->addr,
 41			.flags = priv->i2c->flags,
 42			.len = reg_size,
 43			.buf = (u8 *)reg_buf,
 44		},
 45		{
 46			.addr = priv->i2c->addr,
 47			.flags = priv->i2c->flags | I2C_M_RD,
 48			.len = SMI330_NUM_DUMMY_BYTES + val_size,
 49			.buf = priv->rx_buffer,
 50		},
 51	};
 52
 53	ret = i2c_transfer(priv->i2c->adapter, msgs, ARRAY_SIZE(msgs));
 54	if (ret < 0)
 55		return ret;
 56
 57	memcpy(val_buf, priv->rx_buffer + SMI330_NUM_DUMMY_BYTES, val_size);
 58
 59	return 0;
 60}
 61
 62static int smi330_regmap_i2c_write(void *context, const void *data,
 63				   size_t count)
 64{
 65	struct smi330_i2c_priv *priv = context;
 66	u8 reg;
 67
 68	/*
 69	 * SMI330 I2C write frame:
 70	 * <Slave address[6:0], RnW> <x, Register address[6:0]> <Data_0[7:0]> <Data_1[15:8]>...
 71	 *                                                      <Data_N[7:0]> <Data_N[15:8]>
 72	 * Remark: Slave address is not considered part of the frame in the following definitions
 73	 */
 74	reg = *(u8 *)data;
 75	return i2c_smbus_write_i2c_block_data(priv->i2c, reg,
 76					      count - sizeof(u8),
 77					      data + sizeof(u8));
 78}
 79
 80static const struct regmap_bus smi330_regmap_bus = {
 81	.read = smi330_regmap_i2c_read,
 82	.write = smi330_regmap_i2c_write,
 83};
 84
 85static int smi330_i2c_probe(struct i2c_client *i2c)
 86{
 87	struct device *dev = &i2c->dev;
 88	struct smi330_i2c_priv *priv;
 89	struct regmap *regmap;
 90
 91	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 92	if (!priv)
 93		return -ENOMEM;
 94
 95	priv->i2c = i2c;
 96	regmap = devm_regmap_init(dev, &smi330_regmap_bus, priv,
 97				  &smi330_regmap_config);
 98	if (IS_ERR(regmap))
 99		return dev_err_probe(dev, PTR_ERR(regmap),
100				     "Failed to initialize I2C Regmap\n");
101
102	return smi330_core_probe(dev, regmap);
103}
104
105static const struct i2c_device_id smi330_i2c_device_id[] = {
106	{ .name = "smi330" },
107	{ }
108};
109MODULE_DEVICE_TABLE(i2c, smi330_i2c_device_id);
110
111static const struct of_device_id smi330_of_match[] = {
112	{ .compatible = "bosch,smi330" },
113	{ }
114};
115MODULE_DEVICE_TABLE(of, smi330_of_match);
116
117static struct i2c_driver smi330_i2c_driver = {
118	.probe = smi330_i2c_probe,
119	.id_table = smi330_i2c_device_id,
120	.driver = {
121		.of_match_table = smi330_of_match,
122		.name = "smi330_i2c",
123	},
124};
125module_i2c_driver(smi330_i2c_driver);
126
127MODULE_AUTHOR("Stefan Gutmann <stefan.gutmann@de.bosch.com>");
128MODULE_AUTHOR("Roman Huber <roman.huber@de.bosch.com>");
129MODULE_AUTHOR("Filip Andrei <Andrei.Filip@ro.bosch.com>");
130MODULE_AUTHOR("Drimbarean Avram Andrei <Avram-Andrei.Drimbarean@ro.bosch.com>");
131MODULE_DESCRIPTION("Bosch SMI330 I2C driver");
132MODULE_LICENSE("Dual BSD/GPL");
133MODULE_IMPORT_NS("IIO_SMI330");
~/ Read-only file preview.