From 871480933a1c28f8a9fed4c4d34d06c439a7a422 Mon Sep 17 00:00:00 2001 From: Srikant Patnaik Date: Sun, 11 Jan 2015 12:28:04 +0530 Subject: Moved, renamed, and deleted files The original directory structure was scattered and unorganized. Changes are basically to make it look like kernel structure. --- drivers/input/sensor/mmc328x_msensor/mmc328x.c | 505 +++++++++++++++++++++++++ 1 file changed, 505 insertions(+) create mode 100755 drivers/input/sensor/mmc328x_msensor/mmc328x.c (limited to 'drivers/input/sensor/mmc328x_msensor/mmc328x.c') diff --git a/drivers/input/sensor/mmc328x_msensor/mmc328x.c b/drivers/input/sensor/mmc328x_msensor/mmc328x.c new file mode 100755 index 00000000..4148b5f1 --- /dev/null +++ b/drivers/input/sensor/mmc328x_msensor/mmc328x.c @@ -0,0 +1,505 @@ +/* + * Copyright (C) 2011 MEMSIC, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include "mmc328x.h" +#define DEBUG 0 +#define MAX_FAILURE_COUNT 3 +#define READMD 0 + +#define MMC328X_DELAY_TM 10 /* ms */ +#define MMC328X_DELAY_RM 10 /* ms */ +#define MMC328X_DELAY_STDN 1 /* ms */ +#define MMC328X_DELAY_RRM 1 /* ms */ + +#define MMC328X_RETRY_COUNT 3 +#define MMC328X_RRM_INTV 100 + + +//******************************* move from memsicd 2013-4-26 +#define MMC328X_OFFSET_X 4096 +#define MMC328X_OFFSET_Y 4096 +#define MMC328X_OFFSET_Z 4096 +//****************************************** + +#define MMC328X_DEV_NAME "mmc328x" +#define CONFIG_SENSORS_MMC328xMA_MAG //add rambo 2013-4-20 +struct i2c_client *g_client; + +extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen); +static u32 read_idx = 0; + +static struct i2c_client *this_client; + +static struct wmt_msensor_data l_sensorconfig = { + .op = 0, + .int_gpio = 3, + .samp = 5, + .xyz_axis = { + {ABS_X, -1}, + {ABS_Y, 1}, + {ABS_Z, -1}, + }, + .sensor_proc = NULL, + .isdbg = 0, + .sensor_samp = 10, // 1 sample/second + .sensor_enable = 1, // enable sensor + .test_pass = 0, // for test program + .offset={0,0,0}, +}; + +static int get_axisset(void) +{ + char varbuf[64]; + int n; + int varlen; + + memset(varbuf, 0, sizeof(varbuf)); + varlen = sizeof(varbuf); + if (wmt_getsyspara("wmt.io.msensor328x", varbuf, &varlen)) { + printk("Can't get gsensor config in u-boot!!!!\n"); + //return -1; + } else { + n = sscanf(varbuf, "%d:%d:%d:%d:%d:%d", + + &(l_sensorconfig.xyz_axis[0][0]), + &(l_sensorconfig.xyz_axis[0][1]), + &(l_sensorconfig.xyz_axis[1][0]), + &(l_sensorconfig.xyz_axis[1][1]), + &(l_sensorconfig.xyz_axis[2][0]), + &(l_sensorconfig.xyz_axis[2][1]) + + ); + if (n != 6) { + printk("gsensor format is error in u-boot!!!\n"); + return -1; + } + l_sensorconfig.sensor_samp = l_sensorconfig.samp; + + printk("get the sensor config: %d:%d:%d:%d:%d:%d\n", + + l_sensorconfig.xyz_axis[0][0], + l_sensorconfig.xyz_axis[0][1], + l_sensorconfig.xyz_axis[1][0], + l_sensorconfig.xyz_axis[1][1], + l_sensorconfig.xyz_axis[2][0], + l_sensorconfig.xyz_axis[2][1] + ); + } + return 0; +} + + +static int mmc328x_i2c_rx_data(char *buf, int len) +{ + uint8_t i; + struct i2c_msg msgs[] = { + { + .addr = this_client->addr, + .flags = 0, + .len = 1, + .buf = buf, + }, + { + .addr = this_client->addr, + .flags = I2C_M_RD, + .len = len, + .buf = buf, + } + }; + + for (i = 0; i < MMC328X_RETRY_COUNT; i++) { + if (i2c_transfer(this_client->adapter, msgs, 2) >= 0) { + break; + } + mdelay(10); + } + + if (i >= MMC328X_RETRY_COUNT) { + pr_err("%s: retry over %d\n", __FUNCTION__, MMC328X_RETRY_COUNT); + return -EIO; + } + + return 0; +} + +static int mmc328x_i2c_tx_data(char *buf, int len) +{ + uint8_t i; + struct i2c_msg msg[] = { + { + .addr = this_client->addr, + .flags = 0, + .len = len, + .buf = buf, + } + }; + + for (i = 0; i < MMC328X_RETRY_COUNT; i++) { + if (i2c_transfer(this_client->adapter, msg, 1) >= 0) { + break; + } + mdelay(10); + } + + if (i >= MMC328X_RETRY_COUNT) { + pr_err("%s: retry over %d\n", __FUNCTION__, MMC328X_RETRY_COUNT); + return -EIO; + } + return 0; +} + +static int mmc328x_open(struct inode *inode, struct file *file) +{ + return nonseekable_open(inode, file); +} + +static int mmc328x_release(struct inode *inode, struct file *file) +{ + return 0; +} + +static int mmc328x_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + void __user *pa = (void __user *)arg; + unsigned char data[16] = {0}; + int vec[3] = {0}; + int tmp[3] = {0}; + + int MD_times = 0; + + switch (cmd) { + case MMC328X_IOC_TM: + data[0] = MMC328X_REG_CTRL; + data[1] = MMC328X_CTRL_TM; + if (mmc328x_i2c_tx_data(data, 2) < 0) { + return -EFAULT; + } + /* wait TM done for coming data read */ + msleep(MMC328X_DELAY_TM); + break; + case MMC328X_IOC_RM: + data[0] = MMC328X_REG_CTRL; + data[1] = MMC328X_CTRL_RM; + if (mmc328x_i2c_tx_data(data, 2) < 0) { + return -EFAULT; + } + /* wait external capacitor charging done for next SET*/ + msleep(MMC328X_DELAY_RM); + break; + case MMC328X_IOC_RRM: + data[0] = MMC328X_REG_CTRL; + data[1] = MMC328X_CTRL_RRM; + if (mmc328x_i2c_tx_data(data, 2) < 0) { + return -EFAULT; + } + /* wait external capacitor charging done for next RRM */ + msleep(MMC328X_DELAY_RM); + break; + case MMC328X_IOC_READ: + data[0] = MMC328X_REG_DATA; + if (mmc328x_i2c_rx_data(data, 6) < 0) { + return -EFAULT; + } + tmp[0] = data[1] << 8 | data[0]; + tmp[1] = data[3] << 8 | data[2]; + tmp[2] = data[5] << 8 | data[4]; + tmp[2] = 8192 - tmp[2] ; + //add 2013-4-26 + tmp[0] -= MMC328X_OFFSET_X; + tmp[1] -= MMC328X_OFFSET_Y; + tmp[2] -= MMC328X_OFFSET_Z; + //add end + vec[0] = tmp[l_sensorconfig.xyz_axis[0][0]]*l_sensorconfig.xyz_axis[0][1]; + + vec[1] = tmp[l_sensorconfig.xyz_axis[1][0]]*l_sensorconfig.xyz_axis[1][1]; + + vec[2] = tmp[l_sensorconfig.xyz_axis[2][0]]*l_sensorconfig.xyz_axis[2][1]; + + #if DEBUG + printk("[X - %04x] [Y - %04x] [Z - %04x]\n", + vec[0], vec[1], vec[2]); + #endif + if (copy_to_user(pa, vec, sizeof(vec))) { + return -EFAULT; + } + break; + case MMC328X_IOC_READXYZ: + /* do RM every MMC328X_RRM_INTV times read */ + if (!(read_idx % MMC328X_RRM_INTV)) { +#ifdef CONFIG_SENSORS_MMC328xMA_MAG + data[0] = MMC328X_REG_CTRL; + data[1] = MMC328X_CTRL_RRM; + mmc328x_i2c_tx_data(data, 2); + msleep(MMC328X_DELAY_RRM); +#endif + /* RM */ + data[0] = MMC328X_REG_CTRL; + data[1] = MMC328X_CTRL_RM; + /* not check return value here, assume it always OK */ + mmc328x_i2c_tx_data(data, 2); + /* wait external capacitor charging done for next RM */ + msleep(MMC328X_DELAY_RM); + } + read_idx++; + + /* send TM cmd before read */ + data[0] = MMC328X_REG_CTRL; + data[1] = MMC328X_CTRL_TM; + /* not check return value here, assume it always OK */ + mmc328x_i2c_tx_data(data, 2); + /* wait TM done for coming data read */ + msleep(MMC328X_DELAY_TM); +#if READMD + /* Read MD */ + data[0] = MMC328X_REG_DS; + if (mmc328x_i2c_rx_data(data, 1) < 0) { + return -EFAULT; + } + while (!(data[0] & 0x01)) { + msleep(1); + /* Read MD again*/ + data[0] = MMC328X_REG_DS; + if (mmc328x_i2c_rx_data(data, 1) < 0) { + return -EFAULT; + } + + if (data[0] & 0x01) break; + MD_times++; + if (MD_times > 2) { + #if DEBUG + printk("TM not work!!"); + #endif + return -EFAULT; + } + } +#endif + /* read xyz raw data */ + data[0] = MMC328X_REG_DATA; + if (mmc328x_i2c_rx_data(data, 6) < 0) { + return -EFAULT; + } + tmp[0] = data[1] << 8 | data[0]; + tmp[1] = data[3] << 8 | data[2]; + tmp[2] = data[5] << 8 | data[4]; + tmp[2] = 8192 - tmp[2]; + //add 2013-4-26 + tmp[0] -= MMC328X_OFFSET_X; + tmp[1] -= MMC328X_OFFSET_Y; + tmp[2] -= MMC328X_OFFSET_Z; + //add + vec[0] = tmp[l_sensorconfig.xyz_axis[0][0]]*l_sensorconfig.xyz_axis[0][1]; + + vec[1] = tmp[l_sensorconfig.xyz_axis[1][0]]*l_sensorconfig.xyz_axis[1][1]; + + vec[2] = tmp[l_sensorconfig.xyz_axis[2][0]]*l_sensorconfig.xyz_axis[2][1]; + + + + #if DEBUG + printk("[X - %04x] [Y - %04x] [Z - %04x]\n", + vec[0], vec[1], vec[2]); + #endif + if (copy_to_user(pa, vec, sizeof(vec))) { + return -EFAULT; + } + + break; + default: + break; + } + + return 0; +} + +static ssize_t mmc328x_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + + sprintf(buf, "MMC328X");//!!! + ret = strlen(buf) + 1; + + return ret; +} + +static DEVICE_ATTR(mmc328x, S_IRUGO, mmc328x_show, NULL); + +static struct file_operations mmc328x_fops = { + .owner = THIS_MODULE, + .open = mmc328x_open, + .release = mmc328x_release, + .unlocked_ioctl = mmc328x_ioctl, +}; + +static struct miscdevice mmc328x_device = { + .minor = MISC_DYNAMIC_MINOR, + .name = MMC328X_DEV_NAME, + .fops = &mmc328x_fops, +}; + +static int mmc328x_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + unsigned char data[16] = {0}; + int res = 0; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + pr_err("%s: functionality check failed\n", __FUNCTION__); + res = -ENODEV; + goto out; + } + this_client = client; + + res = misc_register(&mmc328x_device);// + if (res) { + pr_err("%s: mmc328x_device register failed\n", __FUNCTION__); + goto out; + } + res = device_create_file(&client->dev, &dev_attr_mmc328x);// + if (res) { + pr_err("%s: device_create_file failed\n", __FUNCTION__); + goto out_deregister; + } + + /* send RM/RRM cmd to mag sensor first of all */ +#ifdef CONFIG_SENSORS_MMC328xMA_MAG + data[0] = MMC328X_REG_CTRL; + data[1] = MMC328X_CTRL_RRM; + if (mmc328x_i2c_tx_data(data, 2) < 0) { + } + msleep(MMC328X_DELAY_RRM); + data[0] = MMC328X_REG_CTRL; + data[1] = MMC328X_CTRL_TM; + if (mmc328x_i2c_tx_data(data, 2) < 0) { + } + msleep(5*MMC328X_DELAY_TM); +#endif + + data[0] = MMC328X_REG_CTRL; + data[1] = MMC328X_CTRL_RM; + if (mmc328x_i2c_tx_data(data, 2) < 0) { + /* assume RM always success */ + } +#ifndef CONFIG_SENSORS_MMC328xMA_MAG + /* wait external capacitor charging done for next RM */ + msleep(MMC328X_DELAY_RM); +#else + msleep(10*MMC328X_DELAY_RM); + data[0] = MMC328X_REG_CTRL; + data[1] = MMC328X_CTRL_TM; + if (mmc328x_i2c_tx_data(data, 2) < 0) { + } +#endif + + return 0; + +out_deregister: + misc_deregister(&mmc328x_device); +out: + return res; +} + +static int mmc328x_remove(struct i2c_client *client) +{ + device_remove_file(&client->dev, &dev_attr_mmc328x); + misc_deregister(&mmc328x_device); + + return 0; +} + +static const struct i2c_device_id mmc328x_id[] = { + { MMC328X_I2C_NAME, 0 }, + { } +}; + +static struct i2c_driver mmc328x_driver = { + .probe = mmc328x_probe, + .remove = mmc328x_remove, + .id_table = mmc328x_id, + .driver = { + .owner = THIS_MODULE, + .name = MMC328X_I2C_NAME, + }, +}; + +//****************************add by rambo to create i2c client 2013-4-18 +static struct i2c_board_info mmc328x_board_info = +{ + .type = MMC328X_I2C_NAME, + .addr = MMC328X_I2C_ADDR, +}; + +//****************************************** + +static int __init mmc328x_init(void) +{ + int ret; + pr_info("mmc328x driver: init\n"); + + ret = get_axisset(); + struct i2c_adapter *adapter; + adapter = i2c_get_adapter(0); + if (!adapter) + { + printk("<<<<<%s i2c get adapter fail!\n", __FUNCTION__); + return -1; + } + g_client = i2c_new_device(adapter, &mmc328x_board_info); + if (!g_client) + { + printk("<<<<%s i2c new device fail!\n", __FUNCTION__); + i2c_put_adapter(adapter); + return -1; + } + i2c_put_adapter(adapter); + + return i2c_add_driver(&mmc328x_driver); +} + +static void __exit mmc328x_exit(void) +{ + if (g_client != NULL) + { + i2c_unregister_device(g_client); + } + pr_info("mmc328x driver: exit\n"); + i2c_del_driver(&mmc328x_driver); +} + +module_init(mmc328x_init); +module_exit(mmc328x_exit); + +MODULE_DESCRIPTION("MEMSIC MMC328X Magnetic Sensor Driver"); +MODULE_LICENSE("GPL"); + -- cgit