1commit 394498df4ce4d9210b288f64b8f647d9548437ef 2Author: zhaoxc0502 <zhaoxc0502@thundersoft.com> 3Date: Thu Jun 16 17:20:25 2022 +0800 4 5 linux_drivers_hwmon 6 7 Change-Id: If793e9451c0d46dfd159c40fa40b5d0323b0b908 8 9diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig 10index a850e4f0e..a851e65c2 100644 11--- a/drivers/hwmon/Kconfig 12+++ b/drivers/hwmon/Kconfig 13@@ -2123,4 +2123,11 @@ config SENSORS_ATK0110 14 15 endif # ACPI 16 17+ 18+config MXC_MMA8451 19+ tristate "MMA8451 device driver" 20+ depends on I2C 21+ select INPUT_POLLDEV 22+ default y 23+ 24 endif # HWMON 25diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile 26index 9db2903b6..b7898587c 100644 27--- a/drivers/hwmon/Makefile 28+++ b/drivers/hwmon/Makefile 29@@ -193,6 +193,7 @@ obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o 30 obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o 31 obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o 32 obj-$(CONFIG_SENSORS_XGENE) += xgene-hwmon.o 33+obj-$(CONFIG_MXC_MMA8451) += mxc_mma8451.o 34 35 obj-$(CONFIG_SENSORS_OCC) += occ/ 36 obj-$(CONFIG_PMBUS) += pmbus/ 37diff --git a/drivers/hwmon/mxc_mma8451.c b/drivers/hwmon/mxc_mma8451.c 38new file mode 100644 39index 000000000..3c6dbbe71 40--- /dev/null 41+++ b/drivers/hwmon/mxc_mma8451.c 42@@ -0,0 +1,603 @@ 43+/* 44+ * mma8451.c - Linux kernel modules for 3-Axis Orientation/Motion 45+ * Detection Sensor 46+ * 47+ * Copyright (C) 2010-2014 Freescale Semiconductor, Inc. All Rights Reserved. 48+ * 49+ * This program is free software; you can redistribute it and/or modify 50+ * it under the terms of the GNU General Public License as published by 51+ * the Free Software Foundation; either version 2 of the License, or 52+ * (at your option) any later version. 53+ * 54+ * This program is distributed in the hope that it will be useful, 55+ * but WITHOUT ANY WARRANTY; without even the implied warranty of 56+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 57+ * GNU General Public License for more details. 58+ * 59+ * You should have received a copy of the GNU General Public License 60+ * along with this program; if not, write to the Free Software 61+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 62+ */ 63+ 64+#include <linux/module.h> 65+#include <linux/init.h> 66+#include <linux/slab.h> 67+#include <linux/i2c.h> 68+#include <linux/pm.h> 69+#include <linux/mutex.h> 70+#include <linux/delay.h> 71+#include <linux/interrupt.h> 72+#include <linux/irq.h> 73+#include <linux/hwmon-sysfs.h> 74+#include <linux/err.h> 75+#include <linux/hwmon.h> 76+#include <linux/input-polldev.h> 77+#include <linux/of.h> 78+#include <linux/regulator/consumer.h> 79+ 80+#define MMA8451_I2C_ADDR 0x1C 81+#define MMA8451_ID 0x1A 82+#define MMA8452_ID 0x2A 83+#define MMA8453_ID 0x3A 84+ 85+#define POLL_INTERVAL_MIN 1 86+#define POLL_INTERVAL_MAX 500 87+#define POLL_INTERVAL 100 /* msecs */ 88+#define INPUT_FUZZ 32 89+#define INPUT_FLAT 32 90+#define MODE_CHANGE_DELAY_MS 100 91+ 92+#define MMA8451_STATUS_ZYXDR 0x08 93+#define MMA8451_BUF_SIZE 7 94+#define DEFAULT_POSITION 0 95+ 96+/* register enum for mma8451 registers */ 97+enum { 98+ MMA8451_STATUS = 0x00, 99+ MMA8451_OUT_X_MSB, 100+ MMA8451_OUT_X_LSB, 101+ MMA8451_OUT_Y_MSB, 102+ MMA8451_OUT_Y_LSB, 103+ MMA8451_OUT_Z_MSB, 104+ MMA8451_OUT_Z_LSB, 105+ 106+ MMA8451_F_SETUP = 0x09, 107+ MMA8451_TRIG_CFG, 108+ MMA8451_SYSMOD, 109+ MMA8451_INT_SOURCE, 110+ MMA8451_WHO_AM_I, 111+ MMA8451_XYZ_DATA_CFG, 112+ MMA8451_HP_FILTER_CUTOFF, 113+ 114+ MMA8451_PL_STATUS, 115+ MMA8451_PL_CFG, 116+ MMA8451_PL_COUNT, 117+ MMA8451_PL_BF_ZCOMP, 118+ MMA8451_P_L_THS_REG, 119+ 120+ MMA8451_FF_MT_CFG, 121+ MMA8451_FF_MT_SRC, 122+ MMA8451_FF_MT_THS, 123+ MMA8451_FF_MT_COUNT, 124+ 125+ MMA8451_TRANSIENT_CFG = 0x1D, 126+ MMA8451_TRANSIENT_SRC, 127+ MMA8451_TRANSIENT_THS, 128+ MMA8451_TRANSIENT_COUNT, 129+ 130+ MMA8451_PULSE_CFG, 131+ MMA8451_PULSE_SRC, 132+ MMA8451_PULSE_THSX, 133+ MMA8451_PULSE_THSY, 134+ MMA8451_PULSE_THSZ, 135+ MMA8451_PULSE_TMLT, 136+ MMA8451_PULSE_LTCY, 137+ MMA8451_PULSE_WIND, 138+ 139+ MMA8451_ASLP_COUNT, 140+ MMA8451_CTRL_REG1, 141+ MMA8451_CTRL_REG2, 142+ MMA8451_CTRL_REG3, 143+ MMA8451_CTRL_REG4, 144+ MMA8451_CTRL_REG5, 145+ 146+ MMA8451_OFF_X, 147+ MMA8451_OFF_Y, 148+ MMA8451_OFF_Z, 149+ 150+ MMA8451_REG_END, 151+}; 152+ 153+/* The sensitivity is represented in counts/g. In 2g mode the 154+sensitivity is 1024 counts/g. In 4g mode the sensitivity is 512 155+counts/g and in 8g mode the sensitivity is 256 counts/g. 156+ */ 157+enum { 158+ MODE_2G = 0, 159+ MODE_4G, 160+ MODE_8G, 161+}; 162+ 163+enum { 164+ MMA_STANDBY = 0, 165+ MMA_ACTIVED, 166+}; 167+ 168+/* mma8451 status */ 169+struct mma8451_status { 170+ u8 mode; 171+ u8 ctl_reg1; 172+ int active; 173+ int position; 174+}; 175+ 176+static struct mma8451_status mma_status; 177+static struct input_polled_dev *mma8451_idev; 178+static struct device *hwmon_dev; 179+static struct i2c_client *mma8451_i2c_client; 180+ 181+static int senstive_mode = MODE_2G; 182+static int ACCHAL[8][3][3] = { 183+ { {0, -1, 0}, {1, 0, 0}, {0, 0, 1} }, 184+ { {-1, 0, 0}, {0, -1, 0}, {0, 0, 1} }, 185+ { {0, 1, 0}, {-1, 0, 0}, {0, 0, 1} }, 186+ { {1, 0, 0}, {0, 1, 0}, {0, 0, 1} }, 187+ 188+ { {0, -1, 0}, {-1, 0, 0}, {0, 0, -1} }, 189+ { {-1, 0, 0}, {0, 1, 0}, {0, 0, -1} }, 190+ { {0, 1, 0}, {1, 0, 0}, {0, 0, -1} }, 191+ { {1, 0, 0}, {0, -1, 0}, {0, 0, -1} }, 192+}; 193+ 194+static DEFINE_MUTEX(mma8451_lock); 195+static int mma8451_adjust_position(short *x, short *y, short *z) 196+{ 197+ short rawdata[3], data[3]; 198+ int i, j; 199+ int position = mma_status.position; 200+ if (position < 0 || position > 7) 201+ position = 0; 202+ rawdata[0] = *x; 203+ rawdata[1] = *y; 204+ rawdata[2] = *z; 205+ for (i = 0; i < 3; i++) { 206+ data[i] = 0; 207+ for (j = 0; j < 3; j++) 208+ data[i] += rawdata[j] * ACCHAL[position][i][j]; 209+ } 210+ *x = data[0]; 211+ *y = data[1]; 212+ *z = data[2]; 213+ return 0; 214+} 215+ 216+static int mma8451_change_mode(struct i2c_client *client, int mode) 217+{ 218+ int result; 219+ 220+ mma_status.ctl_reg1 = 0; 221+ result = i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1, 0); 222+ if (result < 0) 223+ goto out; 224+ mma_status.active = MMA_STANDBY; 225+ 226+ result = i2c_smbus_write_byte_data(client, MMA8451_XYZ_DATA_CFG, 227+ mode); 228+ if (result < 0) 229+ goto out; 230+ mdelay(MODE_CHANGE_DELAY_MS); 231+ mma_status.mode = mode; 232+ 233+ return 0; 234+out: 235+ dev_err(&client->dev, "error when init mma8451:(%d)", result); 236+ return result; 237+} 238+ 239+static int mma8451_read_data(short *x, short *y, short *z) 240+{ 241+ u8 tmp_data[MMA8451_BUF_SIZE]; 242+ int ret; 243+ 244+ ret = i2c_smbus_read_i2c_block_data(mma8451_i2c_client, 245+ MMA8451_OUT_X_MSB, 7, tmp_data); 246+ if (ret < MMA8451_BUF_SIZE) { 247+ dev_err(&mma8451_i2c_client->dev, "i2c block read failed\n"); 248+ return -EIO; 249+ } 250+ 251+ *x = ((tmp_data[0] << 8) & 0xff00) | tmp_data[1]; 252+ *y = ((tmp_data[2] << 8) & 0xff00) | tmp_data[3]; 253+ *z = ((tmp_data[4] << 8) & 0xff00) | tmp_data[5]; 254+ return 0; 255+} 256+ 257+static void report_abs(void) 258+{ 259+ short x, y, z; 260+ int result; 261+ int retry = 3; 262+ 263+ mutex_lock(&mma8451_lock); 264+ if (mma_status.active == MMA_STANDBY) 265+ goto out; 266+ /* wait for the data ready */ 267+ do { 268+ result = i2c_smbus_read_byte_data(mma8451_i2c_client, 269+ MMA8451_STATUS); 270+ retry--; 271+ msleep(1); 272+ } while (!(result & MMA8451_STATUS_ZYXDR) && retry > 0); 273+ if (retry == 0) 274+ goto out; 275+ if (mma8451_read_data(&x, &y, &z) != 0) 276+ goto out; 277+ mma8451_adjust_position(&x, &y, &z); 278+ input_report_abs(mma8451_idev->input, ABS_X, x); 279+ input_report_abs(mma8451_idev->input, ABS_Y, y); 280+ input_report_abs(mma8451_idev->input, ABS_Z, z); 281+ input_sync(mma8451_idev->input); 282+out: 283+ mutex_unlock(&mma8451_lock); 284+} 285+ 286+static void mma8451_dev_poll(struct input_polled_dev *dev) 287+{ 288+ report_abs(); 289+} 290+ 291+static ssize_t mma8451_enable_show(struct device *dev, 292+ struct device_attribute *attr, char *buf) 293+{ 294+ struct i2c_client *client; 295+ u8 val; 296+ int enable; 297+ 298+ mutex_lock(&mma8451_lock); 299+ client = mma8451_i2c_client; 300+ val = i2c_smbus_read_byte_data(client, MMA8451_CTRL_REG1); 301+ if ((val & 0x01) && mma_status.active == MMA_ACTIVED) 302+ enable = 1; 303+ else 304+ enable = 0; 305+ mutex_unlock(&mma8451_lock); 306+ return sprintf(buf, "%d\n", enable); 307+} 308+ 309+static ssize_t mma8451_enable_store(struct device *dev, 310+ struct device_attribute *attr, 311+ const char *buf, size_t count) 312+{ 313+ struct i2c_client *client; 314+ int ret; 315+ unsigned long enable; 316+ u8 val = 0; 317+ 318+ ret = kstrtoul(buf, 10, &enable); 319+ if (ret) { 320+ dev_err(dev, "string transform error\n"); 321+ return ret; 322+ } 323+ 324+ mutex_lock(&mma8451_lock); 325+ client = mma8451_i2c_client; 326+ enable = (enable > 0) ? 1 : 0; 327+ if (enable && mma_status.active == MMA_STANDBY) { 328+ val = i2c_smbus_read_byte_data(client, MMA8451_CTRL_REG1); 329+ ret = 330+ i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1, 331+ val | 0x01); 332+ if (!ret) 333+ mma_status.active = MMA_ACTIVED; 334+ 335+ } else if (enable == 0 && mma_status.active == MMA_ACTIVED) { 336+ val = i2c_smbus_read_byte_data(client, MMA8451_CTRL_REG1); 337+ ret = 338+ i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1, 339+ val & 0xFE); 340+ if (!ret) 341+ mma_status.active = MMA_STANDBY; 342+ 343+ } 344+ mutex_unlock(&mma8451_lock); 345+ return count; 346+} 347+ 348+static ssize_t mma8451_position_show(struct device *dev, 349+ struct device_attribute *attr, char *buf) 350+{ 351+ int position = 0; 352+ mutex_lock(&mma8451_lock); 353+ position = mma_status.position; 354+ mutex_unlock(&mma8451_lock); 355+ return sprintf(buf, "%d\n", position); 356+} 357+ 358+static ssize_t mma8451_position_store(struct device *dev, 359+ struct device_attribute *attr, 360+ const char *buf, size_t count) 361+{ 362+ unsigned long position; 363+ int ret; 364+ ret = kstrtoul(buf, 10, &position); 365+ if (ret) { 366+ dev_err(dev, "string transform error\n"); 367+ return ret; 368+ } 369+ 370+ mutex_lock(&mma8451_lock); 371+ mma_status.position = (int)position; 372+ mutex_unlock(&mma8451_lock); 373+ return count; 374+} 375+ 376+static ssize_t mma8451_scalemode_show(struct device *dev, 377+ struct device_attribute *attr, 378+ char *buf) 379+{ 380+ int mode = 0; 381+ mutex_lock(&mma8451_lock); 382+ mode = (int)mma_status.mode; 383+ mutex_unlock(&mma8451_lock); 384+ 385+ return sprintf(buf, "%d\n", mode); 386+} 387+ 388+static ssize_t mma8451_scalemode_store(struct device *dev, 389+ struct device_attribute *attr, 390+ const char *buf, size_t count) 391+{ 392+ unsigned long mode; 393+ int ret, active_save; 394+ struct i2c_client *client = mma8451_i2c_client; 395+ 396+ ret = kstrtoul(buf, 10, &mode); 397+ if (ret) { 398+ dev_err(dev, "string transform error\n"); 399+ goto out; 400+ } 401+ 402+ if (mode > MODE_8G) { 403+ dev_warn(dev, "not supported mode\n"); 404+ ret = count; 405+ goto out; 406+ } 407+ 408+ mutex_lock(&mma8451_lock); 409+ if (mode == mma_status.mode) { 410+ ret = count; 411+ goto out_unlock; 412+ } 413+ 414+ active_save = mma_status.active; 415+ ret = mma8451_change_mode(client, mode); 416+ if (ret) 417+ goto out_unlock; 418+ 419+ if (active_save == MMA_ACTIVED) { 420+ ret = i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1, 1); 421+ 422+ if (ret) 423+ goto out_unlock; 424+ mma_status.active = active_save; 425+ } 426+ 427+out_unlock: 428+ mutex_unlock(&mma8451_lock); 429+out: 430+ return ret; 431+} 432+ 433+static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO, 434+ mma8451_enable_show, mma8451_enable_store); 435+static DEVICE_ATTR(position, S_IWUSR | S_IRUGO, 436+ mma8451_position_show, mma8451_position_store); 437+static DEVICE_ATTR(scalemode, S_IWUSR | S_IRUGO, 438+ mma8451_scalemode_show, mma8451_scalemode_store); 439+ 440+static struct attribute *mma8451_attributes[] = { 441+ &dev_attr_enable.attr, 442+ &dev_attr_position.attr, 443+ &dev_attr_scalemode.attr, 444+ NULL 445+}; 446+ 447+static const struct attribute_group mma8451_attr_group = { 448+ .attrs = mma8451_attributes, 449+}; 450+ 451+static int mma8451_probe(struct i2c_client *client, 452+ const struct i2c_device_id *id) 453+{ 454+ int result, client_id; 455+ struct input_dev *idev; 456+ struct i2c_adapter *adapter; 457+ u32 pos; 458+ struct device_node *of_node = client->dev.of_node; 459+ struct regulator *vdd, *vdd_io; 460+ 461+ mma8451_i2c_client = client; 462+ 463+ vdd = devm_regulator_get(&client->dev, "vdd"); 464+ if (!IS_ERR(vdd)) { 465+ result = regulator_enable(vdd); 466+ if (result) { 467+ dev_err(&client->dev, "vdd set voltage error\n"); 468+ return result; 469+ } 470+ } 471+ 472+ vdd_io = devm_regulator_get(&client->dev, "vddio"); 473+ if (!IS_ERR(vdd_io)) { 474+ result = regulator_enable(vdd_io); 475+ if (result) { 476+ dev_err(&client->dev, "vddio set voltage error\n"); 477+ return result; 478+ } 479+ } 480+ 481+ adapter = to_i2c_adapter(client->dev.parent); 482+ result = i2c_check_functionality(adapter, 483+ I2C_FUNC_SMBUS_BYTE | 484+ I2C_FUNC_SMBUS_BYTE_DATA); 485+ if (!result) 486+ goto err_out; 487+ 488+ client_id = i2c_smbus_read_byte_data(client, MMA8451_WHO_AM_I); 489+ if (client_id != MMA8451_ID && client_id != MMA8452_ID 490+ && client_id != MMA8453_ID) { 491+ dev_err(&client->dev, 492+ "read chip ID 0x%x is not equal to 0x%x or 0x%x!\n", 493+ result, MMA8451_ID, MMA8452_ID); 494+ result = -EINVAL; 495+ goto err_out; 496+ } 497+ 498+ /* Initialize the MMA8451 chip */ 499+ result = mma8451_change_mode(client, senstive_mode); 500+ if (result) { 501+ dev_err(&client->dev, 502+ "error when init mma8451 chip:(%d)\n", result); 503+ goto err_out; 504+ } 505+ 506+ hwmon_dev = hwmon_device_register(&client->dev); 507+ if (!hwmon_dev) { 508+ result = -ENOMEM; 509+ dev_err(&client->dev, "error when register hwmon device\n"); 510+ goto err_out; 511+ } 512+ 513+ mma8451_idev = input_allocate_polled_device(); 514+ if (!mma8451_idev) { 515+ result = -ENOMEM; 516+ dev_err(&client->dev, "alloc poll device failed!\n"); 517+ goto err_alloc_poll_device; 518+ } 519+ mma8451_idev->poll = mma8451_dev_poll; 520+ mma8451_idev->poll_interval = POLL_INTERVAL; 521+ mma8451_idev->poll_interval_min = POLL_INTERVAL_MIN; 522+ mma8451_idev->poll_interval_max = POLL_INTERVAL_MAX; 523+ idev = mma8451_idev->input; 524+ idev->name = "mma845x"; 525+ idev->id.bustype = BUS_I2C; 526+ idev->evbit[0] = BIT_MASK(EV_ABS); 527+ 528+ input_set_abs_params(idev, ABS_X, -8192, 8191, INPUT_FUZZ, INPUT_FLAT); 529+ input_set_abs_params(idev, ABS_Y, -8192, 8191, INPUT_FUZZ, INPUT_FLAT); 530+ input_set_abs_params(idev, ABS_Z, -8192, 8191, INPUT_FUZZ, INPUT_FLAT); 531+ 532+ result = input_register_polled_device(mma8451_idev); 533+ if (result) { 534+ dev_err(&client->dev, "register poll device failed!\n"); 535+ goto err_register_polled_device; 536+ } 537+ result = sysfs_create_group(&idev->dev.kobj, &mma8451_attr_group); 538+ if (result) { 539+ dev_err(&client->dev, "create device file failed!\n"); 540+ result = -EINVAL; 541+ goto err_register_polled_device; 542+ } 543+ 544+ result = of_property_read_u32(of_node, "position", &pos); 545+ if (result) 546+ pos = DEFAULT_POSITION; 547+ mma_status.position = (int)pos; 548+ 549+ return 0; 550+err_register_polled_device: 551+ input_free_polled_device(mma8451_idev); 552+err_alloc_poll_device: 553+ hwmon_device_unregister(&client->dev); 554+err_out: 555+ if (!IS_ERR(vdd)) 556+ regulator_disable(vdd); 557+ if (!IS_ERR(vdd_io)) 558+ regulator_disable(vdd_io); 559+ return result; 560+} 561+ 562+static int mma8451_stop_chip(struct i2c_client *client) 563+{ 564+ int ret = 0; 565+ if (mma_status.active == MMA_ACTIVED) { 566+ mma_status.ctl_reg1 = i2c_smbus_read_byte_data(client, 567+ MMA8451_CTRL_REG1); 568+ ret = i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1, 569+ mma_status.ctl_reg1 & 0xFE); 570+ } 571+ return ret; 572+} 573+ 574+static int mma8451_remove(struct i2c_client *client) 575+{ 576+ int ret; 577+ ret = mma8451_stop_chip(client); 578+ hwmon_device_unregister(hwmon_dev); 579+ 580+ return ret; 581+} 582+ 583+#ifdef CONFIG_PM_SLEEP 584+static int mma8451_suspend(struct device *dev) 585+{ 586+ struct i2c_client *client = to_i2c_client(dev); 587+ 588+ return mma8451_stop_chip(client); 589+} 590+ 591+static int mma8451_resume(struct device *dev) 592+{ 593+ int ret = 0; 594+ struct i2c_client *client = to_i2c_client(dev); 595+ if (mma_status.active == MMA_ACTIVED) 596+ ret = i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1, 597+ mma_status.ctl_reg1); 598+ return ret; 599+ 600+} 601+#endif 602+ 603+static const struct i2c_device_id mma8451_id[] = { 604+ {"mma8451", 0}, 605+ { /* sentinel */ } 606+}; 607+ 608+MODULE_DEVICE_TABLE(i2c, mma8451_id); 609+ 610+static SIMPLE_DEV_PM_OPS(mma8451_pm_ops, mma8451_suspend, mma8451_resume); 611+static struct i2c_driver mma8451_driver = { 612+ .driver = { 613+ .name = "mma8451", 614+ .owner = THIS_MODULE, 615+ .pm = &mma8451_pm_ops, 616+ }, 617+ .probe = mma8451_probe, 618+ .remove = mma8451_remove, 619+ .id_table = mma8451_id, 620+}; 621+ 622+static int __init mma8451_init(void) 623+{ 624+ /* register driver */ 625+ int res; 626+ 627+ res = i2c_add_driver(&mma8451_driver); 628+ if (res < 0) { 629+ printk(KERN_INFO "add mma8451 i2c driver failed\n"); 630+ return -ENODEV; 631+ } 632+ return res; 633+} 634+ 635+static void __exit mma8451_exit(void) 636+{ 637+ i2c_del_driver(&mma8451_driver); 638+} 639+ 640+MODULE_AUTHOR("Freescale Semiconductor, Inc."); 641+MODULE_DESCRIPTION("MMA8451 3-Axis Orientation/Motion Detection Sensor driver"); 642+MODULE_LICENSE("GPL"); 643+ 644+module_init(mma8451_init); 645+module_exit(mma8451_exit); 646