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