[T106][ZXW-22]7520V3SCV2.01.01.02P42U09_VEC_V0.8_AP_VEC origin source commit
Change-Id: Ic6e05d89ecd62fc34f82b23dcf306c93764aec4b
diff --git a/ap/os/linux/linux-3.4.x/drivers/mfd/zx234290-i2c.c b/ap/os/linux/linux-3.4.x/drivers/mfd/zx234290-i2c.c
new file mode 100644
index 0000000..a4c5c2f
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/drivers/mfd/zx234290-i2c.c
@@ -0,0 +1,304 @@
+/*
+ * zx234290-i2c.c -- I2C access for ZTE ZX234290 PMIC
+ *
+ * Copyright 2016 ZTE Inc.
+ *
+ * Author: yuxiang<yu.xiang5@zte.com.cn>
+ *
+ * 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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/zx234290.h>
+#include <linux/wakelock.h>
+
+static struct i2c_client *zx234290_i2c =0;
+static DEFINE_MUTEX(zx234290_i2c_lock);
+
+int zx29_i2c_xfer_PSM(struct i2c_adapter *adap, struct i2c_msg *msgs, int num);
+#if 1
+int zx234290_i2c_read_simple(u8 reg, void *dest)
+{
+ mutex_lock(&zx234290_i2c_lock);
+// struct i2c_client *i2c = zx234290->control_data;
+ struct i2c_client *i2c = zx234290_i2c;
+ struct i2c_msg xfer[2];
+ int ret;
+
+ /* Write register */
+ xfer[0].addr = i2c->addr;
+ xfer[0].flags = 0;
+ xfer[0].len = 1;
+ xfer[0].buf = ®
+
+ /* Read data */
+ xfer[1].addr = i2c->addr;
+ xfer[1].flags = I2C_M_RD;
+ xfer[1].len = 1;
+ xfer[1].buf = dest;
+
+ ret = i2c_transfer(i2c->adapter, xfer, 2);
+ if (ret == 2)
+ ret = 0;
+ else if (ret >= 0)
+ {
+ ret = -EIO;
+
+ printk(KERN_INFO "[zx234290 i2c]read-1 error. reg:%x\n", reg);
+ }
+ mutex_unlock(&zx234290_i2c_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(zx234290_i2c_read_simple);
+
+int zx234290_i2c_read_simple_PSM(u8 reg, void *dest)
+{
+// struct i2c_client *i2c = zx234290->control_data;
+ struct i2c_client *i2c = zx234290_i2c;
+ struct i2c_msg xfer[2];
+ int ret;
+
+ /* Write register */
+ xfer[0].addr = i2c->addr;
+ xfer[0].flags = 0;
+ xfer[0].len = 1;
+ xfer[0].buf = ®
+
+ /* Read data */
+ xfer[1].addr = i2c->addr;
+ xfer[1].flags = I2C_M_RD;
+ xfer[1].len = 1;
+ xfer[1].buf = dest;
+
+ ret = zx29_i2c_xfer_PSM(i2c->adapter, xfer, 2);
+ if (ret == 2)
+ ret = 0;
+ else
+ {
+ ret = -EIO;
+
+ printk(KERN_INFO "[zx234290 i2c]read-psm error. reg:%x\n", reg);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(zx234290_i2c_read_simple_PSM);
+
+int zx234290_i2c_write_simple(u8 reg, void *src)
+{
+ mutex_lock(&zx234290_i2c_lock);
+// struct i2c_client *i2c = zx234290->control_data;
+ struct i2c_client *i2c = zx234290_i2c;
+ /* we add 1 byte for device register */
+ u8 msg[4];
+ int ret;
+
+ //if (reg > ZX234290_MAX_REGISTER)
+ // return -EINVAL;
+
+ msg[0] = reg;
+ memcpy(&msg[1], src, 1);
+
+ ret = i2c_master_send(i2c, msg, 1 + 1);
+ if (ret < 0){
+ mutex_unlock(&zx234290_i2c_lock);
+
+ printk(KERN_INFO "[zx234290 i2c]write-3 error. reg:%x\n", reg);
+
+ return ret;
+ }
+ if (ret != 1 + 1){
+ mutex_unlock(&zx234290_i2c_lock);
+ printk(KERN_INFO "[zx234290 i2c]write-4 error. reg:%x\n", reg);
+ return -EIO;
+ }
+
+ mutex_unlock(&zx234290_i2c_lock);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(zx234290_i2c_write_simple);
+
+int zx234290_i2c_write_simple_PSM(u8 reg, void *src)
+{
+// struct i2c_client *i2c = zx234290->control_data;
+ struct i2c_client *i2c = zx234290_i2c;
+ /* we add 1 byte for device register */
+ u8 buf[4];
+ int ret;
+ struct i2c_msg msg;
+
+ if (reg > ZX234290_MAX_REGISTER)
+ return -EINVAL;
+
+ buf[0] = reg;
+ memcpy(buf+1, src, 1);
+
+ msg.addr = i2c->addr;
+ msg.flags = 0;
+ msg.len = 2;
+ msg.buf = (char *)buf;
+
+ ret = zx29_i2c_xfer_PSM(i2c->adapter, &msg, 1);
+ if (ret != 1) {
+ printk(KERN_INFO "[zx234290 i2c]write-psm error. reg:%x\n", reg);
+
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(zx234290_i2c_write_simple_PSM);
+#endif
+
+
+
+//static i2c_client *zx234290_i2c=0;
+#if 1
+static int zx234290_i2c_read(struct zx234290 *zx234290, u8 reg,
+ int bytes, void *dest)
+{
+ struct i2c_client *i2c = zx234290->control_data;
+// struct i2c_client *i2c = zx234290_i2c;
+ struct i2c_msg xfer[2];
+ int ret;
+
+ /* Write register */
+ xfer[0].addr = i2c->addr;
+ xfer[0].flags = 0;
+ xfer[0].len = 1;
+ xfer[0].buf = ®
+
+ /* Read data */
+ xfer[1].addr = i2c->addr;
+ xfer[1].flags = I2C_M_RD;
+ xfer[1].len = bytes;
+ xfer[1].buf = dest;
+
+ ret = i2c_transfer(i2c->adapter, xfer, 2);
+ if (ret == 2)
+ ret = 0;
+ else if (ret >= 0)
+ {
+ ret = -EIO;
+
+ printk(KERN_INFO "[zx234290 i2c]read error. reg:%x\n", reg);
+ }
+
+ return ret;
+}
+
+static int zx234290_i2c_write(struct zx234290 *zx234290, u8 reg,
+ int bytes, void *src)
+{
+ struct i2c_client *i2c = zx234290->control_data;
+// struct i2c_client *i2c = zx234290_i2c;
+ /* we add 1 byte for device register */
+ u8 msg[ZX234290_MAX_REGISTER + 1];
+ int ret;
+
+ if (bytes > ZX234290_MAX_REGISTER)
+ return -EINVAL;
+
+ msg[0] = reg;
+ memcpy(&msg[1], src, bytes);
+
+ ret = i2c_master_send(i2c, msg, bytes + 1);
+ if (ret < 0)
+ {
+ printk(KERN_INFO "[zx234290 i2c]write-1 error. reg:%x\n", reg);
+
+ return ret;
+ }
+ if (ret != bytes + 1)
+ {
+ printk(KERN_INFO "[zx234290 i2c]write-2 error. reg:%x\n", reg);
+
+ return -EIO;
+ }
+
+ return 0;
+}
+#endif
+
+static int zx234290_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct zx234290 *zx234290;
+
+ zx234290_i2c = i2c;
+
+ zx234290 = kzalloc(sizeof(struct zx234290), GFP_KERNEL);
+ if (zx234290 == NULL)
+ return -ENOMEM;
+
+ i2c_set_clientdata(i2c, zx234290);
+ zx234290->dev = &i2c->dev;
+ zx234290->control_data = i2c;
+ zx234290->read = zx234290_i2c_read;
+ zx234290->write = zx234290_i2c_write;
+
+ return zx234290_device_init(zx234290);
+}
+
+static int zx234290_i2c_remove(struct i2c_client *i2c)
+{
+ struct zx234290 *zx234290 = i2c_get_clientdata(i2c);
+
+ if(!zx234290)
+ return -EINVAL;
+ zx234290_device_exit(zx234290);
+
+ return 0;
+}
+
+static const struct i2c_device_id zx234290_i2c_id[] = {
+ {"zx234290", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, zx234290_i2c_id);
+
+#if 1
+static struct i2c_driver zx234290_i2c_driver = {
+ .driver = {
+ .name = "zx234290",
+ .owner = THIS_MODULE,
+ },
+ .probe = zx234290_i2c_probe,
+ .remove = zx234290_i2c_remove,
+ .id_table = zx234290_i2c_id,
+};
+#endif
+struct wake_lock adc_wake_lock;
+static int __init zx234290_i2c_init(void)
+{
+ int ret;
+ wake_lock_init(&adc_wake_lock, WAKE_LOCK_SUSPEND, "adc_lock");
+ ret = i2c_add_driver(&zx234290_i2c_driver);
+ if (ret != 0)
+ pr_err("Failed to register ZX234290 I2C driver: %d\n", ret);
+
+ return ret;
+}
+/* init early so consumer devices can complete system boot */
+subsys_initcall(zx234290_i2c_init);
+
+static void __exit zx234290_i2c_exit(void)
+{
+ i2c_del_driver(&zx234290_i2c_driver);
+}
+module_exit(zx234290_i2c_exit);
+
+MODULE_AUTHOR("Dongjian");
+MODULE_DESCRIPTION("ZX234290 chip family multi-function driver");
+MODULE_LICENSE("GPL");