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