1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * 3-axis accelerometer driver supporting following I2C Bosch-Sensortec chips: 4 * - BMC150 5 * - BMI055 6 * - BMA255 7 * - BMA250E 8 * - BMA222 9 * - BMA222E 10 * - BMA280 11 * 12 * Copyright (c) 2014, Intel Corporation. 13 */ 14 15 #include <linux/device.h> 16 #include <linux/mod_devicetable.h> 17 #include <linux/i2c.h> 18 #include <linux/module.h> 19 #include <linux/acpi.h> 20 #include <linux/regmap.h> 21 22 #include "bmc150-accel.h" 23 24 #ifdef CONFIG_ACPI 25 static const struct acpi_device_id bmc150_acpi_dual_accel_ids[] = { 26 {"BOSC0200"}, 27 {"DUAL250E"}, 28 { } 29 }; 30 31 /* 32 * Some acpi_devices describe 2 accelerometers in a single ACPI device, 33 * try instantiating a second i2c_client for an I2cSerialBusV2 ACPI resource 34 * with index 1. 35 */ 36 static void bmc150_acpi_dual_accel_probe(struct i2c_client *client) 37 { 38 struct acpi_device *adev = ACPI_COMPANION(&client->dev); 39 struct i2c_client *second_dev; 40 char dev_name[16]; 41 struct i2c_board_info board_info = { 42 .type = "bmc150_accel", 43 .dev_name = dev_name, 44 .fwnode = client->dev.fwnode, 45 }; 46 47 if (acpi_match_device_ids(adev, bmc150_acpi_dual_accel_ids)) 48 return; 49 50 /* 51 * The 2nd accel sits in the base of 2-in-1s. The suffix is static, as 52 * there should never be more then 1 ACPI node with 2 accelerometers. 53 */ 54 snprintf(dev_name, sizeof(dev_name), "%s:base", acpi_device_hid(adev)); 55 56 board_info.irq = acpi_dev_gpio_irq_get(adev, 1); 57 58 second_dev = i2c_acpi_new_device(&client->dev, 1, &board_info); 59 if (!IS_ERR(second_dev)) 60 bmc150_set_second_device(client, second_dev); 61 } 62 63 static void bmc150_acpi_dual_accel_remove(struct i2c_client *client) 64 { 65 struct i2c_client *second_dev = bmc150_get_second_device(client); 66 67 i2c_unregister_device(second_dev); 68 } 69 #else 70 static void bmc150_acpi_dual_accel_probe(struct i2c_client *client) {} 71 static void bmc150_acpi_dual_accel_remove(struct i2c_client *client) {} 72 #endif 73 74 static int bmc150_accel_probe(struct i2c_client *client, 75 const struct i2c_device_id *id) 76 { 77 struct regmap *regmap; 78 const char *name = NULL; 79 bool block_supported = 80 i2c_check_functionality(client->adapter, I2C_FUNC_I2C) || 81 i2c_check_functionality(client->adapter, 82 I2C_FUNC_SMBUS_READ_I2C_BLOCK); 83 int ret; 84 85 regmap = devm_regmap_init_i2c(client, &bmc150_regmap_conf); 86 if (IS_ERR(regmap)) { 87 dev_err(&client->dev, "Failed to initialize i2c regmap\n"); 88 return PTR_ERR(regmap); 89 } 90 91 if (id) 92 name = id->name; 93 94 ret = bmc150_accel_core_probe(&client->dev, regmap, client->irq, name, block_supported); 95 if (ret) 96 return ret; 97 98 /* 99 * The !id check avoids recursion when probe() gets called 100 * for the second client. 101 */ 102 if (!id && has_acpi_companion(&client->dev)) 103 bmc150_acpi_dual_accel_probe(client); 104 105 return 0; 106 } 107 108 static int bmc150_accel_remove(struct i2c_client *client) 109 { 110 bmc150_acpi_dual_accel_remove(client); 111 112 return bmc150_accel_core_remove(&client->dev); 113 } 114 115 static const struct acpi_device_id bmc150_accel_acpi_match[] = { 116 {"BSBA0150", bmc150}, 117 {"BMC150A", bmc150}, 118 {"BMI055A", bmi055}, 119 {"BMA0255", bma255}, 120 {"BMA250E", bma250e}, 121 {"BMA222", bma222}, 122 {"BMA222E", bma222e}, 123 {"BMA0280", bma280}, 124 {"BOSC0200"}, 125 {"DUAL250E"}, 126 { }, 127 }; 128 MODULE_DEVICE_TABLE(acpi, bmc150_accel_acpi_match); 129 130 static const struct i2c_device_id bmc150_accel_id[] = { 131 {"bmc150_accel", bmc150}, 132 {"bmi055_accel", bmi055}, 133 {"bma255", bma255}, 134 {"bma250e", bma250e}, 135 {"bma222", bma222}, 136 {"bma222e", bma222e}, 137 {"bma280", bma280}, 138 {} 139 }; 140 141 MODULE_DEVICE_TABLE(i2c, bmc150_accel_id); 142 143 static const struct of_device_id bmc150_accel_of_match[] = { 144 { .compatible = "bosch,bmc150_accel" }, 145 { .compatible = "bosch,bmi055_accel" }, 146 { .compatible = "bosch,bma255" }, 147 { .compatible = "bosch,bma250e" }, 148 { .compatible = "bosch,bma222" }, 149 { .compatible = "bosch,bma222e" }, 150 { .compatible = "bosch,bma280" }, 151 { }, 152 }; 153 MODULE_DEVICE_TABLE(of, bmc150_accel_of_match); 154 155 static struct i2c_driver bmc150_accel_driver = { 156 .driver = { 157 .name = "bmc150_accel_i2c", 158 .of_match_table = bmc150_accel_of_match, 159 .acpi_match_table = ACPI_PTR(bmc150_accel_acpi_match), 160 .pm = &bmc150_accel_pm_ops, 161 }, 162 .probe = bmc150_accel_probe, 163 .remove = bmc150_accel_remove, 164 .id_table = bmc150_accel_id, 165 }; 166 module_i2c_driver(bmc150_accel_driver); 167 168 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); 169 MODULE_LICENSE("GPL v2"); 170 MODULE_DESCRIPTION("BMC150 I2C accelerometer driver"); 171