blob: a4c5c2f85b01f209146a0d958f14f296b393a428 [file] [log] [blame]
/*
* 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 = &reg;
/* 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 = &reg;
/* 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 = &reg;
/* 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");