xref: /linux/drivers/iio/imu/inv_icm42607/inv_icm42607_spi.c (revision 67f8bc848ee31831336bd478e57d2f993551902e)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (C) 2026 InvenSense, Inc.
4  */
5 
6 #include <linux/bitfield.h>
7 #include <linux/dev_printk.h>
8 #include <linux/err.h>
9 #include <linux/module.h>
10 #include <linux/regmap.h>
11 #include <linux/spi/spi.h>
12 
13 #include "inv_icm42607.h"
14 
15 static int inv_icm42607_spi_bus_setup(struct inv_icm42607_state *st)
16 {
17 	unsigned int val;
18 	int ret;
19 
20 	/* Only support 4-wire mode for now. */
21 	ret = regmap_set_bits(st->map, INV_ICM42607_REG_DEVICE_CONFIG,
22 				      INV_ICM42607_DEVICE_CONFIG_SPI_AP_4WIRE);
23 	if (ret)
24 		return ret;
25 
26 	ret = regmap_clear_bits(st->map, INV_ICM42607_REG_INTF_CONFIG1,
27 				INV_ICM42607_INTF_CONFIG1_I3C_DDR_EN |
28 				INV_ICM42607_INTF_CONFIG1_I3C_SDR_EN);
29 	if (ret)
30 		return ret;
31 
32 	val = FIELD_PREP(INV_ICM42607_DRIVE_CONFIG3_SPI_MASK,
33 			 INV_ICM42607_SLEW_RATE_2NS);
34 	ret = regmap_update_bits(st->map, INV_ICM42607_REG_DRIVE_CONFIG3,
35 				 INV_ICM42607_DRIVE_CONFIG3_SPI_MASK, val);
36 	if (ret)
37 		return ret;
38 
39 	val = FIELD_PREP(INV_ICM42607_INTF_CONFIG0_UI_SIFS_CFG_MASK,
40 			 INV_ICM42607_INTF_CONFIG0_UI_SIFS_CFG_I2C_DIS);
41 
42 	return regmap_update_bits(st->map, INV_ICM42607_REG_INTF_CONFIG0,
43 				  INV_ICM42607_INTF_CONFIG0_UI_SIFS_CFG_MASK,
44 				  val);
45 }
46 
47 static int inv_icm42607_probe(struct spi_device *spi)
48 {
49 	const struct inv_icm42607_hw *hw;
50 	struct device *dev = &spi->dev;
51 	struct regmap *regmap;
52 
53 	hw = spi_get_device_match_data(spi);
54 	if (!hw)
55 		return dev_err_probe(dev, -ENODATA, "Failed to get SPI data\n");
56 
57 	if (spi->mode & SPI_3WIRE)
58 		return dev_err_probe(dev, -ENODEV, "SPI 3-wire mode not supported\n");
59 
60 	regmap = devm_regmap_init_spi(spi, &inv_icm42607_regmap_config);
61 	if (IS_ERR(regmap))
62 		return dev_err_probe(dev, PTR_ERR(regmap),
63 				     "Failed to register spi regmap\n");
64 
65 	return inv_icm42607_core_probe(regmap, hw, inv_icm42607_spi_bus_setup);
66 }
67 
68 static const struct spi_device_id inv_icm42607_spi_id_table[] = {
69 	{
70 		.name = "icm42607",
71 		.driver_data = (kernel_ulong_t)&inv_icm42607_hw_data,
72 	}, {
73 		.name = "icm42607p",
74 		.driver_data = (kernel_ulong_t)&inv_icm42607p_hw_data,
75 	},
76 	{ }
77 };
78 MODULE_DEVICE_TABLE(spi, inv_icm42607_spi_id_table);
79 
80 static const struct of_device_id inv_icm42607_of_matches[] = {
81 	{
82 		.compatible = "invensense,icm42607",
83 		.data = &inv_icm42607_hw_data,
84 	},
85 	{
86 		.compatible = "invensense,icm42607p",
87 		.data = &inv_icm42607p_hw_data,
88 	},
89 	{ }
90 };
91 MODULE_DEVICE_TABLE(of, inv_icm42607_of_matches);
92 
93 static struct spi_driver inv_icm42607_driver = {
94 	.driver = {
95 		.name = "inv-icm42607-spi",
96 		.of_match_table = inv_icm42607_of_matches,
97 		.pm = pm_ptr(&inv_icm42607_pm_ops),
98 	},
99 	.id_table = inv_icm42607_spi_id_table,
100 	.probe = inv_icm42607_probe,
101 };
102 module_spi_driver(inv_icm42607_driver);
103 
104 MODULE_AUTHOR("InvenSense, Inc.");
105 MODULE_DESCRIPTION("InvenSense ICM-42607 SPI driver");
106 MODULE_LICENSE("GPL");
107 MODULE_IMPORT_NS("IIO_ICM42607");
108