xref: /linux/drivers/iio/imu/inv_icm42607/inv_icm42607_spi.c (revision 67f8bc848ee31831336bd478e57d2f993551902e)
1337cb9a3SChris Morgan // SPDX-License-Identifier: GPL-2.0-or-later
2337cb9a3SChris Morgan /*
3337cb9a3SChris Morgan  * Copyright (C) 2026 InvenSense, Inc.
4337cb9a3SChris Morgan  */
5337cb9a3SChris Morgan 
6337cb9a3SChris Morgan #include <linux/bitfield.h>
7337cb9a3SChris Morgan #include <linux/dev_printk.h>
8337cb9a3SChris Morgan #include <linux/err.h>
9337cb9a3SChris Morgan #include <linux/module.h>
10337cb9a3SChris Morgan #include <linux/regmap.h>
11337cb9a3SChris Morgan #include <linux/spi/spi.h>
12337cb9a3SChris Morgan 
13337cb9a3SChris Morgan #include "inv_icm42607.h"
14337cb9a3SChris Morgan 
15337cb9a3SChris Morgan static int inv_icm42607_spi_bus_setup(struct inv_icm42607_state *st)
16337cb9a3SChris Morgan {
17337cb9a3SChris Morgan 	unsigned int val;
18337cb9a3SChris Morgan 	int ret;
19337cb9a3SChris Morgan 
20337cb9a3SChris Morgan 	/* Only support 4-wire mode for now. */
21337cb9a3SChris Morgan 	ret = regmap_set_bits(st->map, INV_ICM42607_REG_DEVICE_CONFIG,
22337cb9a3SChris Morgan 				      INV_ICM42607_DEVICE_CONFIG_SPI_AP_4WIRE);
23337cb9a3SChris Morgan 	if (ret)
24337cb9a3SChris Morgan 		return ret;
25337cb9a3SChris Morgan 
26337cb9a3SChris Morgan 	ret = regmap_clear_bits(st->map, INV_ICM42607_REG_INTF_CONFIG1,
27337cb9a3SChris Morgan 				INV_ICM42607_INTF_CONFIG1_I3C_DDR_EN |
28337cb9a3SChris Morgan 				INV_ICM42607_INTF_CONFIG1_I3C_SDR_EN);
29337cb9a3SChris Morgan 	if (ret)
30337cb9a3SChris Morgan 		return ret;
31337cb9a3SChris Morgan 
32337cb9a3SChris Morgan 	val = FIELD_PREP(INV_ICM42607_DRIVE_CONFIG3_SPI_MASK,
33337cb9a3SChris Morgan 			 INV_ICM42607_SLEW_RATE_2NS);
34337cb9a3SChris Morgan 	ret = regmap_update_bits(st->map, INV_ICM42607_REG_DRIVE_CONFIG3,
35337cb9a3SChris Morgan 				 INV_ICM42607_DRIVE_CONFIG3_SPI_MASK, val);
36337cb9a3SChris Morgan 	if (ret)
37337cb9a3SChris Morgan 		return ret;
38337cb9a3SChris Morgan 
39337cb9a3SChris Morgan 	val = FIELD_PREP(INV_ICM42607_INTF_CONFIG0_UI_SIFS_CFG_MASK,
40337cb9a3SChris Morgan 			 INV_ICM42607_INTF_CONFIG0_UI_SIFS_CFG_I2C_DIS);
41337cb9a3SChris Morgan 
42337cb9a3SChris Morgan 	return regmap_update_bits(st->map, INV_ICM42607_REG_INTF_CONFIG0,
43337cb9a3SChris Morgan 				  INV_ICM42607_INTF_CONFIG0_UI_SIFS_CFG_MASK,
44337cb9a3SChris Morgan 				  val);
45337cb9a3SChris Morgan }
46337cb9a3SChris Morgan 
47337cb9a3SChris Morgan static int inv_icm42607_probe(struct spi_device *spi)
48337cb9a3SChris Morgan {
49337cb9a3SChris Morgan 	const struct inv_icm42607_hw *hw;
50337cb9a3SChris Morgan 	struct device *dev = &spi->dev;
51337cb9a3SChris Morgan 	struct regmap *regmap;
52337cb9a3SChris Morgan 
53337cb9a3SChris Morgan 	hw = spi_get_device_match_data(spi);
54337cb9a3SChris Morgan 	if (!hw)
55337cb9a3SChris Morgan 		return dev_err_probe(dev, -ENODATA, "Failed to get SPI data\n");
56337cb9a3SChris Morgan 
57337cb9a3SChris Morgan 	if (spi->mode & SPI_3WIRE)
58337cb9a3SChris Morgan 		return dev_err_probe(dev, -ENODEV, "SPI 3-wire mode not supported\n");
59337cb9a3SChris Morgan 
60337cb9a3SChris Morgan 	regmap = devm_regmap_init_spi(spi, &inv_icm42607_regmap_config);
61337cb9a3SChris Morgan 	if (IS_ERR(regmap))
62337cb9a3SChris Morgan 		return dev_err_probe(dev, PTR_ERR(regmap),
63337cb9a3SChris Morgan 				     "Failed to register spi regmap\n");
64337cb9a3SChris Morgan 
65337cb9a3SChris Morgan 	return inv_icm42607_core_probe(regmap, hw, inv_icm42607_spi_bus_setup);
66337cb9a3SChris Morgan }
67337cb9a3SChris Morgan 
68337cb9a3SChris Morgan static const struct spi_device_id inv_icm42607_spi_id_table[] = {
69337cb9a3SChris Morgan 	{
70337cb9a3SChris Morgan 		.name = "icm42607",
71337cb9a3SChris Morgan 		.driver_data = (kernel_ulong_t)&inv_icm42607_hw_data,
72337cb9a3SChris Morgan 	}, {
73337cb9a3SChris Morgan 		.name = "icm42607p",
74337cb9a3SChris Morgan 		.driver_data = (kernel_ulong_t)&inv_icm42607p_hw_data,
75337cb9a3SChris Morgan 	},
76337cb9a3SChris Morgan 	{ }
77337cb9a3SChris Morgan };
78337cb9a3SChris Morgan MODULE_DEVICE_TABLE(spi, inv_icm42607_spi_id_table);
79337cb9a3SChris Morgan 
80337cb9a3SChris Morgan static const struct of_device_id inv_icm42607_of_matches[] = {
81337cb9a3SChris Morgan 	{
82337cb9a3SChris Morgan 		.compatible = "invensense,icm42607",
83337cb9a3SChris Morgan 		.data = &inv_icm42607_hw_data,
84337cb9a3SChris Morgan 	},
85337cb9a3SChris Morgan 	{
86337cb9a3SChris Morgan 		.compatible = "invensense,icm42607p",
87337cb9a3SChris Morgan 		.data = &inv_icm42607p_hw_data,
88337cb9a3SChris Morgan 	},
89337cb9a3SChris Morgan 	{ }
90337cb9a3SChris Morgan };
91337cb9a3SChris Morgan MODULE_DEVICE_TABLE(of, inv_icm42607_of_matches);
92337cb9a3SChris Morgan 
93337cb9a3SChris Morgan static struct spi_driver inv_icm42607_driver = {
94337cb9a3SChris Morgan 	.driver = {
95337cb9a3SChris Morgan 		.name = "inv-icm42607-spi",
96337cb9a3SChris Morgan 		.of_match_table = inv_icm42607_of_matches,
97*3007c153SChris Morgan 		.pm = pm_ptr(&inv_icm42607_pm_ops),
98337cb9a3SChris Morgan 	},
99337cb9a3SChris Morgan 	.id_table = inv_icm42607_spi_id_table,
100337cb9a3SChris Morgan 	.probe = inv_icm42607_probe,
101337cb9a3SChris Morgan };
102337cb9a3SChris Morgan module_spi_driver(inv_icm42607_driver);
103337cb9a3SChris Morgan 
104337cb9a3SChris Morgan MODULE_AUTHOR("InvenSense, Inc.");
105337cb9a3SChris Morgan MODULE_DESCRIPTION("InvenSense ICM-42607 SPI driver");
106337cb9a3SChris Morgan MODULE_LICENSE("GPL");
107337cb9a3SChris Morgan MODULE_IMPORT_NS("IIO_ICM42607");
108