19f9ff91bSJean-Baptiste Maneyrol // SPDX-License-Identifier: GPL-2.0-or-later 29f9ff91bSJean-Baptiste Maneyrol /* 39f9ff91bSJean-Baptiste Maneyrol * Copyright (C) 2020 InvenSense, Inc. 49f9ff91bSJean-Baptiste Maneyrol */ 59f9ff91bSJean-Baptiste Maneyrol 69f9ff91bSJean-Baptiste Maneyrol #include <linux/kernel.h> 79f9ff91bSJean-Baptiste Maneyrol #include <linux/device.h> 89f9ff91bSJean-Baptiste Maneyrol #include <linux/module.h> 99f9ff91bSJean-Baptiste Maneyrol #include <linux/mod_devicetable.h> 109f9ff91bSJean-Baptiste Maneyrol #include <linux/spi/spi.h> 119f9ff91bSJean-Baptiste Maneyrol #include <linux/regmap.h> 129f9ff91bSJean-Baptiste Maneyrol #include <linux/property.h> 139f9ff91bSJean-Baptiste Maneyrol 149f9ff91bSJean-Baptiste Maneyrol #include "inv_icm42600.h" 159f9ff91bSJean-Baptiste Maneyrol 169f9ff91bSJean-Baptiste Maneyrol static int inv_icm42600_spi_bus_setup(struct inv_icm42600_state *st) 179f9ff91bSJean-Baptiste Maneyrol { 189f9ff91bSJean-Baptiste Maneyrol unsigned int mask, val; 199f9ff91bSJean-Baptiste Maneyrol int ret; 209f9ff91bSJean-Baptiste Maneyrol 219f9ff91bSJean-Baptiste Maneyrol /* setup interface registers */ 229f9ff91bSJean-Baptiste Maneyrol val = INV_ICM42600_INTF_CONFIG6_I3C_EN | 239f9ff91bSJean-Baptiste Maneyrol INV_ICM42600_INTF_CONFIG6_I3C_SDR_EN | 249f9ff91bSJean-Baptiste Maneyrol INV_ICM42600_INTF_CONFIG6_I3C_DDR_EN; 259f9ff91bSJean-Baptiste Maneyrol ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG6, 269f9ff91bSJean-Baptiste Maneyrol INV_ICM42600_INTF_CONFIG6_MASK, val); 279f9ff91bSJean-Baptiste Maneyrol if (ret) 289f9ff91bSJean-Baptiste Maneyrol return ret; 299f9ff91bSJean-Baptiste Maneyrol 309f9ff91bSJean-Baptiste Maneyrol ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG4, 319f9ff91bSJean-Baptiste Maneyrol INV_ICM42600_INTF_CONFIG4_I3C_BUS_ONLY, 0); 329f9ff91bSJean-Baptiste Maneyrol if (ret) 339f9ff91bSJean-Baptiste Maneyrol return ret; 349f9ff91bSJean-Baptiste Maneyrol 359f9ff91bSJean-Baptiste Maneyrol /* set slew rates for I2C and SPI */ 369f9ff91bSJean-Baptiste Maneyrol mask = INV_ICM42600_DRIVE_CONFIG_I2C_MASK | 379f9ff91bSJean-Baptiste Maneyrol INV_ICM42600_DRIVE_CONFIG_SPI_MASK; 389f9ff91bSJean-Baptiste Maneyrol val = INV_ICM42600_DRIVE_CONFIG_I2C(INV_ICM42600_SLEW_RATE_20_60NS) | 399f9ff91bSJean-Baptiste Maneyrol INV_ICM42600_DRIVE_CONFIG_SPI(INV_ICM42600_SLEW_RATE_INF_2NS); 409f9ff91bSJean-Baptiste Maneyrol ret = regmap_update_bits(st->map, INV_ICM42600_REG_DRIVE_CONFIG, 419f9ff91bSJean-Baptiste Maneyrol mask, val); 429f9ff91bSJean-Baptiste Maneyrol if (ret) 439f9ff91bSJean-Baptiste Maneyrol return ret; 449f9ff91bSJean-Baptiste Maneyrol 459f9ff91bSJean-Baptiste Maneyrol /* disable i2c bus */ 469f9ff91bSJean-Baptiste Maneyrol return regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG0, 479f9ff91bSJean-Baptiste Maneyrol INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_MASK, 489f9ff91bSJean-Baptiste Maneyrol INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_I2C_DIS); 499f9ff91bSJean-Baptiste Maneyrol } 509f9ff91bSJean-Baptiste Maneyrol 519f9ff91bSJean-Baptiste Maneyrol static int inv_icm42600_probe(struct spi_device *spi) 529f9ff91bSJean-Baptiste Maneyrol { 539f9ff91bSJean-Baptiste Maneyrol const void *match; 549f9ff91bSJean-Baptiste Maneyrol enum inv_icm42600_chip chip; 559f9ff91bSJean-Baptiste Maneyrol struct regmap *regmap; 569f9ff91bSJean-Baptiste Maneyrol 579f9ff91bSJean-Baptiste Maneyrol match = device_get_match_data(&spi->dev); 589f9ff91bSJean-Baptiste Maneyrol if (!match) 599f9ff91bSJean-Baptiste Maneyrol return -EINVAL; 60*072cc981SJonathan Cameron chip = (uintptr_t)match; 619f9ff91bSJean-Baptiste Maneyrol 629f9ff91bSJean-Baptiste Maneyrol regmap = devm_regmap_init_spi(spi, &inv_icm42600_regmap_config); 639f9ff91bSJean-Baptiste Maneyrol if (IS_ERR(regmap)) 649f9ff91bSJean-Baptiste Maneyrol return PTR_ERR(regmap); 659f9ff91bSJean-Baptiste Maneyrol 66e5efa104SJean-Baptiste Maneyrol return inv_icm42600_core_probe(regmap, chip, spi->irq, 67e5efa104SJean-Baptiste Maneyrol inv_icm42600_spi_bus_setup); 689f9ff91bSJean-Baptiste Maneyrol } 699f9ff91bSJean-Baptiste Maneyrol 709f9ff91bSJean-Baptiste Maneyrol static const struct of_device_id inv_icm42600_of_matches[] = { 719f9ff91bSJean-Baptiste Maneyrol { 729f9ff91bSJean-Baptiste Maneyrol .compatible = "invensense,icm42600", 739f9ff91bSJean-Baptiste Maneyrol .data = (void *)INV_CHIP_ICM42600, 749f9ff91bSJean-Baptiste Maneyrol }, { 759f9ff91bSJean-Baptiste Maneyrol .compatible = "invensense,icm42602", 769f9ff91bSJean-Baptiste Maneyrol .data = (void *)INV_CHIP_ICM42602, 779f9ff91bSJean-Baptiste Maneyrol }, { 789f9ff91bSJean-Baptiste Maneyrol .compatible = "invensense,icm42605", 799f9ff91bSJean-Baptiste Maneyrol .data = (void *)INV_CHIP_ICM42605, 809f9ff91bSJean-Baptiste Maneyrol }, { 819f9ff91bSJean-Baptiste Maneyrol .compatible = "invensense,icm42622", 829f9ff91bSJean-Baptiste Maneyrol .data = (void *)INV_CHIP_ICM42622, 839f9ff91bSJean-Baptiste Maneyrol }, 849f9ff91bSJean-Baptiste Maneyrol {} 859f9ff91bSJean-Baptiste Maneyrol }; 869f9ff91bSJean-Baptiste Maneyrol MODULE_DEVICE_TABLE(of, inv_icm42600_of_matches); 879f9ff91bSJean-Baptiste Maneyrol 889f9ff91bSJean-Baptiste Maneyrol static struct spi_driver inv_icm42600_driver = { 899f9ff91bSJean-Baptiste Maneyrol .driver = { 909f9ff91bSJean-Baptiste Maneyrol .name = "inv-icm42600-spi", 919f9ff91bSJean-Baptiste Maneyrol .of_match_table = inv_icm42600_of_matches, 929f9ff91bSJean-Baptiste Maneyrol .pm = &inv_icm42600_pm_ops, 939f9ff91bSJean-Baptiste Maneyrol }, 949f9ff91bSJean-Baptiste Maneyrol .probe = inv_icm42600_probe, 959f9ff91bSJean-Baptiste Maneyrol }; 969f9ff91bSJean-Baptiste Maneyrol module_spi_driver(inv_icm42600_driver); 979f9ff91bSJean-Baptiste Maneyrol 989f9ff91bSJean-Baptiste Maneyrol MODULE_AUTHOR("InvenSense, Inc."); 999f9ff91bSJean-Baptiste Maneyrol MODULE_DESCRIPTION("InvenSense ICM-426xx SPI driver"); 1009f9ff91bSJean-Baptiste Maneyrol MODULE_LICENSE("GPL"); 101