0001
0002
0003
0004
0005
0006
0007 #include <linux/device.h>
0008 #include <linux/mod_devicetable.h>
0009 #include <linux/i2c.h>
0010 #include <linux/module.h>
0011 #include <linux/acpi.h>
0012 #include <linux/regmap.h>
0013
0014 #include "bmc150-accel.h"
0015
0016 #ifdef CONFIG_ACPI
0017 static const struct acpi_device_id bmc150_acpi_dual_accel_ids[] = {
0018 {"BOSC0200"},
0019 {"DUAL250E"},
0020 { }
0021 };
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040 #define BMC150_DSM_GUID "7681541e-8827-4239-8d9d-36be7fe12542"
0041 #define DUAL250E_SET_ANGLE_FN_INDEX 3
0042
0043 struct dual250e_set_angle_args {
0044 u32 aux0;
0045 u32 ang0;
0046 u32 rawx;
0047 u32 rawy;
0048 u32 rawz;
0049 } __packed;
0050
0051 static bool bmc150_acpi_set_angle_dsm(struct i2c_client *client, u32 aux0, u32 ang0)
0052 {
0053 struct acpi_device *adev = ACPI_COMPANION(&client->dev);
0054 struct dual250e_set_angle_args args = {
0055 .aux0 = aux0,
0056 .ang0 = ang0,
0057 };
0058 union acpi_object args_obj, *obj;
0059 guid_t guid;
0060
0061 if (!acpi_dev_hid_uid_match(adev, "DUAL250E", NULL))
0062 return false;
0063
0064 guid_parse(BMC150_DSM_GUID, &guid);
0065
0066 if (!acpi_check_dsm(adev->handle, &guid, 0, BIT(DUAL250E_SET_ANGLE_FN_INDEX)))
0067 return false;
0068
0069
0070
0071
0072
0073
0074
0075
0076 args_obj.type = ACPI_TYPE_BUFFER;
0077 args_obj.buffer.length = sizeof(args);
0078 args_obj.buffer.pointer = (u8 *)&args;
0079
0080 obj = acpi_evaluate_dsm(adev->handle, &guid, 0, DUAL250E_SET_ANGLE_FN_INDEX, &args_obj);
0081 if (!obj) {
0082 dev_err(&client->dev, "Failed to call DSM to enable keyboard and touchpad\n");
0083 return false;
0084 }
0085
0086 ACPI_FREE(obj);
0087 return true;
0088 }
0089
0090 static bool bmc150_acpi_enable_keyboard(struct i2c_client *client)
0091 {
0092
0093
0094
0095
0096
0097 if (!bmc150_acpi_set_angle_dsm(client, 0, 270))
0098 return false;
0099
0100
0101 msleep(100);
0102
0103 return bmc150_acpi_set_angle_dsm(client, 0, 90);
0104 }
0105
0106 static void bmc150_acpi_resume_work(struct work_struct *work)
0107 {
0108 struct bmc150_accel_data *data =
0109 container_of(work, struct bmc150_accel_data, resume_work.work);
0110
0111 bmc150_acpi_enable_keyboard(data->second_device);
0112 }
0113
0114 static void bmc150_acpi_resume_handler(struct device *dev)
0115 {
0116 struct bmc150_accel_data *data = iio_priv(dev_get_drvdata(dev));
0117
0118
0119
0120
0121
0122 schedule_delayed_work(&data->resume_work, msecs_to_jiffies(1000));
0123 }
0124
0125
0126
0127
0128
0129
0130 static void bmc150_acpi_dual_accel_probe(struct i2c_client *client)
0131 {
0132 struct bmc150_accel_data *data = iio_priv(i2c_get_clientdata(client));
0133 struct acpi_device *adev = ACPI_COMPANION(&client->dev);
0134 char dev_name[16];
0135 struct i2c_board_info board_info = {
0136 .type = "bmc150_accel",
0137 .dev_name = dev_name,
0138 .fwnode = client->dev.fwnode,
0139 };
0140
0141 if (acpi_match_device_ids(adev, bmc150_acpi_dual_accel_ids))
0142 return;
0143
0144
0145
0146
0147
0148 snprintf(dev_name, sizeof(dev_name), "%s:base", acpi_device_hid(adev));
0149
0150 board_info.irq = acpi_dev_gpio_irq_get(adev, 1);
0151
0152 data->second_device = i2c_acpi_new_device(&client->dev, 1, &board_info);
0153
0154 if (!IS_ERR(data->second_device) && bmc150_acpi_enable_keyboard(data->second_device)) {
0155 INIT_DELAYED_WORK(&data->resume_work, bmc150_acpi_resume_work);
0156 data->resume_callback = bmc150_acpi_resume_handler;
0157 }
0158 }
0159
0160 static void bmc150_acpi_dual_accel_remove(struct i2c_client *client)
0161 {
0162 struct bmc150_accel_data *data = iio_priv(i2c_get_clientdata(client));
0163
0164 if (data->resume_callback)
0165 cancel_delayed_work_sync(&data->resume_work);
0166
0167 i2c_unregister_device(data->second_device);
0168 }
0169 #else
0170 static void bmc150_acpi_dual_accel_probe(struct i2c_client *client) {}
0171 static void bmc150_acpi_dual_accel_remove(struct i2c_client *client) {}
0172 #endif
0173
0174 static int bmc150_accel_probe(struct i2c_client *client,
0175 const struct i2c_device_id *id)
0176 {
0177 struct regmap *regmap;
0178 const char *name = NULL;
0179 enum bmc150_type type = BOSCH_UNKNOWN;
0180 bool block_supported =
0181 i2c_check_functionality(client->adapter, I2C_FUNC_I2C) ||
0182 i2c_check_functionality(client->adapter,
0183 I2C_FUNC_SMBUS_READ_I2C_BLOCK);
0184 int ret;
0185
0186 regmap = devm_regmap_init_i2c(client, &bmc150_regmap_conf);
0187 if (IS_ERR(regmap)) {
0188 dev_err(&client->dev, "Failed to initialize i2c regmap\n");
0189 return PTR_ERR(regmap);
0190 }
0191
0192 if (id) {
0193 name = id->name;
0194 type = id->driver_data;
0195 }
0196
0197 ret = bmc150_accel_core_probe(&client->dev, regmap, client->irq,
0198 type, name, block_supported);
0199 if (ret)
0200 return ret;
0201
0202
0203
0204
0205
0206 if (!id && has_acpi_companion(&client->dev))
0207 bmc150_acpi_dual_accel_probe(client);
0208
0209 return 0;
0210 }
0211
0212 static int bmc150_accel_remove(struct i2c_client *client)
0213 {
0214 bmc150_acpi_dual_accel_remove(client);
0215
0216 bmc150_accel_core_remove(&client->dev);
0217
0218 return 0;
0219 }
0220
0221 static const struct acpi_device_id bmc150_accel_acpi_match[] = {
0222 {"BMA0255"},
0223 {"BMA0280"},
0224 {"BMA222"},
0225 {"BMA222E"},
0226 {"BMA250E"},
0227 {"BMC150A"},
0228 {"BMI055A"},
0229 {"BOSC0200"},
0230 {"BSBA0150"},
0231 {"DUAL250E"},
0232 { },
0233 };
0234 MODULE_DEVICE_TABLE(acpi, bmc150_accel_acpi_match);
0235
0236 static const struct i2c_device_id bmc150_accel_id[] = {
0237 {"bma222"},
0238 {"bma222e"},
0239 {"bma250e"},
0240 {"bma253"},
0241 {"bma254"},
0242 {"bma255"},
0243 {"bma280"},
0244 {"bmc150_accel"},
0245 {"bmc156_accel", BOSCH_BMC156},
0246 {"bmi055_accel"},
0247 {}
0248 };
0249
0250 MODULE_DEVICE_TABLE(i2c, bmc150_accel_id);
0251
0252 static const struct of_device_id bmc150_accel_of_match[] = {
0253 { .compatible = "bosch,bma222" },
0254 { .compatible = "bosch,bma222e" },
0255 { .compatible = "bosch,bma250e" },
0256 { .compatible = "bosch,bma253" },
0257 { .compatible = "bosch,bma254" },
0258 { .compatible = "bosch,bma255" },
0259 { .compatible = "bosch,bma280" },
0260 { .compatible = "bosch,bmc150_accel" },
0261 { .compatible = "bosch,bmc156_accel" },
0262 { .compatible = "bosch,bmi055_accel" },
0263 { },
0264 };
0265 MODULE_DEVICE_TABLE(of, bmc150_accel_of_match);
0266
0267 static struct i2c_driver bmc150_accel_driver = {
0268 .driver = {
0269 .name = "bmc150_accel_i2c",
0270 .of_match_table = bmc150_accel_of_match,
0271 .acpi_match_table = ACPI_PTR(bmc150_accel_acpi_match),
0272 .pm = &bmc150_accel_pm_ops,
0273 },
0274 .probe = bmc150_accel_probe,
0275 .remove = bmc150_accel_remove,
0276 .id_table = bmc150_accel_id,
0277 };
0278 module_i2c_driver(bmc150_accel_driver);
0279
0280 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
0281 MODULE_LICENSE("GPL v2");
0282 MODULE_DESCRIPTION("BMC150 I2C accelerometer driver");
0283 MODULE_IMPORT_NS(IIO_BMC150);