summaryrefslogtreecommitdiffstats
path: root/drivers/mfd/twl-core.c
diff options
context:
space:
mode:
authorAlexander Aring <a.aring@phytec.de>2011-12-21 08:50:28 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2011-12-21 12:46:01 +0100
commit5c115f335ec06fa1fd8a28740790a622e500a304 (patch)
treea565f58cd6047911b3d136f6a0e978603a0ea984 /drivers/mfd/twl-core.c
parent8007b25bdfa353cbce71c849a41f474604648ebf (diff)
downloadbarebox-5c115f335ec06fa1fd8a28740790a622e500a304.tar.gz
barebox-5c115f335ec06fa1fd8a28740790a622e500a304.tar.xz
twl-core: abstract twl4030 and add twlcore driver
Add a general twl device driver twlcore to call i2c send/write functions. Abstract twl4030 to call twlcore functions. Fixed some code-styling issues pointed out by checkpatch. Signed-off-by: Alexander Aring <a.aring@phytec.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/mfd/twl-core.c')
-rw-r--r--drivers/mfd/twl-core.c157
1 files changed, 157 insertions, 0 deletions
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
new file mode 100644
index 0000000000..cb2c03dfca
--- /dev/null
+++ b/drivers/mfd/twl-core.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2011 Alexander Aring <a.aring@phytec.de>
+ *
+ * Based on:
+ * Copyright (C) 2010 Michael Grzeschik <mgr@pengutronix.de>
+ *
+ * This file is released under the GPLv2
+ *
+ */
+
+#include <common.h>
+#include <init.h>
+#include <driver.h>
+#include <xfuncs.h>
+#include <errno.h>
+
+#include <i2c/i2c.h>
+#include <mfd/twl-core.h>
+
+#define to_twlcore(a) container_of(a, struct twlcore, cdev)
+
+static struct twlcore *twl_dev;
+
+struct twlcore *twlcore_get(void)
+{
+ return twl_dev;
+}
+EXPORT_SYMBOL(twlcore_get);
+
+int twlcore_reg_read(struct twlcore *twlcore, u16 reg, u8 *val)
+{
+ int ret;
+ struct i2c_msg xfer_msg[2];
+ struct i2c_msg *msg;
+ int i2c_addr;
+ unsigned char buf = reg & 0xff;
+
+ i2c_addr = twlcore->client->addr + (reg / 0x100);
+
+ /* [MSG1] fill the register address data */
+ msg = &xfer_msg[0];
+ msg->addr = i2c_addr;
+ msg->len = 1;
+ msg->flags = 0;
+ msg->buf = &buf;
+ /* [MSG2] fill the data rx buffer */
+ msg = &xfer_msg[1];
+ msg->addr = i2c_addr;
+ msg->flags = I2C_M_RD;
+ msg->len = 1; /* only n bytes */
+ msg->buf = val;
+ ret = i2c_transfer(twlcore->client->adapter, xfer_msg, 2);
+
+ /* i2c_transfer returns number of messages transferred */
+ if (ret < 0) {
+ pr_err("%s: failed to transfer all messages: %s\n",
+ __func__, strerror(-ret));
+ return ret;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(twlcore_reg_read);
+
+int twlcore_reg_write(struct twlcore *twlcore, u16 reg, u8 val)
+{
+ int ret;
+ struct i2c_msg xfer_msg[1];
+ struct i2c_msg *msg;
+ int i2c_addr;
+ u8 buf[2];
+
+ buf[0] = reg & 0xff;
+ buf[1] = val;
+
+ i2c_addr = twlcore->client->addr + (reg / 0x100);
+
+ /*
+ * [MSG1]: fill the register address data
+ * fill the data Tx buffer
+ */
+ msg = xfer_msg;
+ msg->addr = i2c_addr;
+ msg->len = 2;
+ msg->flags = 0;
+ msg->buf = buf;
+ /* over write the first byte of buffer with the register address */
+ ret = i2c_transfer(twlcore->client->adapter, xfer_msg, 1);
+
+ /* i2c_transfer returns number of messages transferred */
+ if (ret < 0) {
+ pr_err("%s: failed to transfer all messages: %s\n",
+ __func__, strerror(-ret));
+ return ret;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(twlcore_reg_write);
+
+int twlcore_set_bits(struct twlcore *twlcore, u16 reg, u8 mask, u8 val)
+{
+ u8 tmp;
+ int ret;
+
+ ret = twlcore_reg_read(twlcore, reg, &tmp);
+ tmp = (tmp & ~mask) | val;
+
+ if (ret)
+ ret = twlcore_reg_write(twlcore, reg, tmp);
+
+ return ret;
+}
+EXPORT_SYMBOL(twlcore_set_bits);
+
+static ssize_t twl_read(struct cdev *cdev, void *_buf, size_t count,
+ ulong offset, ulong flags)
+{
+ struct twlcore *priv = to_twlcore(cdev);
+ u8 *buf = _buf;
+ size_t i;
+ int ret;
+
+ for (i = 0; i < count; i++) {
+ ret = twlcore_reg_read(priv, offset, buf);
+ if (ret)
+ return (ssize_t)ret;
+ buf++;
+ offset++;
+ }
+
+ return count;
+}
+
+static ssize_t twl_write(struct cdev *cdev, const void *_buf, size_t count,
+ ulong offset, ulong flags)
+{
+ struct twlcore *twlcore = to_twlcore(cdev);
+ const u8 *buf = _buf;
+ size_t i;
+ int ret;
+
+ for (i = 0; i < count; i++) {
+ ret = twlcore_reg_write(twlcore, offset, *buf);
+ if (ret)
+ return (ssize_t)ret;
+ buf++;
+ offset++;
+ }
+
+ return count;
+}
+
+struct file_operations twl_fops = {
+ .lseek = dev_lseek_default,
+ .read = twl_read,
+ .write = twl_write,
+};
+EXPORT_SYMBOL(twl_fops);