forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
TPS6507x are multi function (PM, touchscreen) chipsets from TI. This commit also changes the corresponding regulator driver from being standalone to an MFD subdevice. Signed-off-by: Todd Fischer <[email protected]> Acked-by: Mark Brown <[email protected]> Signed-off-by: Liam Girdwood <[email protected]> Signed-off-by: Samuel Ortiz <[email protected]>
- Loading branch information
Showing
5 changed files
with
265 additions
and
79 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
/* | ||
* tps6507x.c -- TPS6507x chip family multi-function driver | ||
* | ||
* Copyright (c) 2010 RidgeRun ([email protected]) | ||
* | ||
* Author: Todd Fischer | ||
* [email protected] | ||
* | ||
* Credits: | ||
* | ||
* Using code from wm831x-*.c, wm8400-core, Wolfson Microelectronics PLC. | ||
* | ||
* For licencing details see kernel-base/COPYING | ||
* | ||
*/ | ||
|
||
#include <linux/module.h> | ||
#include <linux/moduleparam.h> | ||
#include <linux/init.h> | ||
#include <linux/slab.h> | ||
#include <linux/i2c.h> | ||
#include <linux/mfd/core.h> | ||
#include <linux/mfd/tps6507x.h> | ||
|
||
static struct mfd_cell tps6507x_devs[] = { | ||
{ | ||
.name = "tps6507x-pmic", | ||
}, | ||
}; | ||
|
||
|
||
static int tps6507x_i2c_read_device(struct tps6507x_dev *tps6507x, char reg, | ||
int bytes, void *dest) | ||
{ | ||
struct i2c_client *i2c = tps6507x->i2c_client; | ||
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; | ||
|
||
return ret; | ||
} | ||
|
||
static int tps6507x_i2c_write_device(struct tps6507x_dev *tps6507x, char reg, | ||
int bytes, void *src) | ||
{ | ||
struct i2c_client *i2c = tps6507x->i2c_client; | ||
/* we add 1 byte for device register */ | ||
u8 msg[TPS6507X_MAX_REGISTER + 1]; | ||
int ret; | ||
|
||
if (bytes > (TPS6507X_MAX_REGISTER + 1)) | ||
return -EINVAL; | ||
|
||
msg[0] = reg; | ||
memcpy(&msg[1], src, bytes); | ||
|
||
ret = i2c_master_send(i2c, msg, bytes + 1); | ||
if (ret < 0) | ||
return ret; | ||
if (ret != bytes + 1) | ||
return -EIO; | ||
return 0; | ||
} | ||
|
||
static int tps6507x_i2c_probe(struct i2c_client *i2c, | ||
const struct i2c_device_id *id) | ||
{ | ||
struct tps6507x_dev *tps6507x; | ||
int ret = 0; | ||
|
||
tps6507x = kzalloc(sizeof(struct tps6507x_dev), GFP_KERNEL); | ||
if (tps6507x == NULL) { | ||
kfree(i2c); | ||
return -ENOMEM; | ||
} | ||
|
||
i2c_set_clientdata(i2c, tps6507x); | ||
tps6507x->dev = &i2c->dev; | ||
tps6507x->i2c_client = i2c; | ||
tps6507x->read_dev = tps6507x_i2c_read_device; | ||
tps6507x->write_dev = tps6507x_i2c_write_device; | ||
|
||
ret = mfd_add_devices(tps6507x->dev, -1, | ||
tps6507x_devs, ARRAY_SIZE(tps6507x_devs), | ||
NULL, 0); | ||
|
||
if (ret < 0) | ||
goto err; | ||
|
||
return ret; | ||
|
||
err: | ||
mfd_remove_devices(tps6507x->dev); | ||
kfree(tps6507x); | ||
return ret; | ||
} | ||
|
||
static int tps6507x_i2c_remove(struct i2c_client *i2c) | ||
{ | ||
struct tps6507x_dev *tps6507x = i2c_get_clientdata(i2c); | ||
|
||
mfd_remove_devices(tps6507x->dev); | ||
kfree(tps6507x); | ||
|
||
return 0; | ||
} | ||
|
||
static const struct i2c_device_id tps6507x_i2c_id[] = { | ||
{ "tps6507x", 0 }, | ||
{ } | ||
}; | ||
MODULE_DEVICE_TABLE(i2c, tps6507x_i2c_id); | ||
|
||
|
||
static struct i2c_driver tps6507x_i2c_driver = { | ||
.driver = { | ||
.name = "tps6507x", | ||
.owner = THIS_MODULE, | ||
}, | ||
.probe = tps6507x_i2c_probe, | ||
.remove = tps6507x_i2c_remove, | ||
.id_table = tps6507x_i2c_id, | ||
}; | ||
|
||
static int __init tps6507x_i2c_init(void) | ||
{ | ||
return i2c_add_driver(&tps6507x_i2c_driver); | ||
} | ||
/* init early so consumer devices can complete system boot */ | ||
subsys_initcall(tps6507x_i2c_init); | ||
|
||
static void __exit tps6507x_i2c_exit(void) | ||
{ | ||
i2c_del_driver(&tps6507x_i2c_driver); | ||
} | ||
module_exit(tps6507x_i2c_exit); | ||
|
||
MODULE_DESCRIPTION("TPS6507x chip family multi-function driver"); | ||
MODULE_LICENSE("GPL"); |
Oops, something went wrong.