]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00170255-2 MX6Q PFUZE100: add pfuze100 driver
authorRobin Gong <B38343@freescale.com>
Mon, 19 Dec 2011 10:04:47 +0000 (18:04 +0800)
committerOliver Wendt <ow@karo-electronics.de>
Mon, 30 Sep 2013 12:10:24 +0000 (14:10 +0200)
add pfuze core  driver for mx6
Signed-off-by: Robin Gong <B38343@freescale.com>
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/pfuze-core.c [new file with mode: 0644]
include/linux/mfd/pfuze.h [new file with mode: 0644]

index 97f3f9d4f9e1d6ae4ad20451f5ab5a64c605e713..714b0fa625bbc16fb29e78bb0c96ddb7f55070ea 100755 (executable)
@@ -521,7 +521,12 @@ config MFD_MC34708
        select MFD_MC_PMIC
        help
          Support for the Freescale's PMIC MC34708
-
+config MFD_PFUZE
+       tristate "Support for Freescale's PMIC PFUZE"
+       depends on I2C
+       select MFD_CORE
+       help
+        Support for Freescale's PMIC: PFUZE100
 config PCF50633_ADC
        tristate "Support for NXP PCF50633 ADC"
        depends on MFD_PCF50633
index 58cace2fea97937ba7241b273c92caa5796121c7..347f39d66edec37917f9240dcfbc5b1ffc1bc4dd 100755 (executable)
@@ -43,7 +43,7 @@ obj-$(CONFIG_TWL4030_CODEC)   += twl4030-codec.o
 obj-$(CONFIG_TWL6030_PWM)      += twl6030-pwm.o
 obj-$(CONFIG_MFD_MC13XXX)      += mc13xxx-core.o
 obj-$(CONFIG_MFD_MC_PMIC)      += mc-pmic-core.o
-
+obj-$(CONFIG_MFD_PFUZE)                += pfuze-core.o
 obj-$(CONFIG_MFD_CORE)         += mfd-core.o
 
 obj-$(CONFIG_EZX_PCAP)         += ezx-pcap.o
diff --git a/drivers/mfd/pfuze-core.c b/drivers/mfd/pfuze-core.c
new file mode 100644 (file)
index 0000000..ae3a37e
--- /dev/null
@@ -0,0 +1,570 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/slab.h>
+#include <linux/module.h>
+/*#define VERBOSE_DEBUG*/
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/pfuze.h>
+#include <linux/delay.h>
+
+#define PFUZE_REG_DEVICE_ID    0
+#define PFUZE_REG_REVISION_ID  3
+#define PFUZE_REG_FAB_ID       4
+#define PFUZE_REG_INT_STATUS0  5
+#define PFUZE_REG_INT_MASK0    6
+#define PFUZE_REG_INT_SENSE0   7
+
+struct mc_pfuze {
+       struct i2c_client *i2c_client;
+       struct mutex lock;
+       int irq;                /*irq number */
+       irq_handler_t irqhandler[PFUZE_NUM_IRQ];
+       void *irqdata[PFUZE_NUM_IRQ];
+};
+
+static const struct i2c_device_id pfuze_device_id[] = {
+       {"pfuze100", 0},
+       {},
+};
+
+enum pfuze_id {
+       PFUZE_ID_PFUZE100,
+       PFUZE_ID_INVALID,
+};
+static const char *pfuze_chipname[] = {
+       [PFUZE_ID_PFUZE100] = "pfuze100",
+};
+
+void pfuze_lock(struct mc_pfuze *mc_pfuze)
+{
+       if (!mutex_trylock(&mc_pfuze->lock)) {
+               dev_dbg(&mc_pfuze->i2c_client->dev, "wait for %s from %pf\n",
+                       __func__, __builtin_return_address(0));
+               mutex_lock(&mc_pfuze->lock);
+       }
+       dev_dbg(&mc_pfuze->i2c_client->dev, "%s from %pf\n",
+               __func__, __builtin_return_address(0));
+}
+
+EXPORT_SYMBOL(pfuze_lock);
+
+void pfuze_unlock(struct mc_pfuze *mc_pfuze)
+{
+       dev_dbg(&mc_pfuze->i2c_client->dev, "%s from %pf\n", __func__,
+               __builtin_return_address(0));
+       mutex_unlock(&mc_pfuze->lock);
+}
+
+EXPORT_SYMBOL(pfuze_unlock);
+
+int pfuze_reg_read(struct mc_pfuze *mc_pfuze, unsigned int offset,
+                  unsigned char *val)
+{
+       unsigned char data;
+       int ret, i;
+       BUG_ON(!mutex_is_locked(&mc_pfuze->lock));
+       if (offset > PFUZE_NUMREGS)
+               return -EINVAL;
+       data = (unsigned char)offset;
+       for (i = 0; i < PFUZE_I2C_RETRY_TIMES; i++) {
+               ret =
+                   i2c_smbus_read_i2c_block_data(mc_pfuze->i2c_client, data, 1,
+                                                 val);
+               if (ret == 1)
+                       break;
+               msleep(1);
+       }
+       if (ret != 1) {
+               dev_err(&mc_pfuze->i2c_client->dev, "recv failed!:%i,%x\n", ret,
+                       *val);
+               return -1;
+       }
+
+       return 0;
+}
+
+EXPORT_SYMBOL(pfuze_reg_read);
+
+int pfuze_reg_write(struct mc_pfuze *mc_pfuze, unsigned int offset,
+                   unsigned char val)
+{
+       unsigned char buf[2];
+       int ret;
+
+       buf[0] = (unsigned char)offset;
+       memcpy(&buf[1], &val, 1);
+
+       ret = i2c_master_send(mc_pfuze->i2c_client, buf, 2);
+       if (ret != 2) {
+               dev_err(&mc_pfuze->i2c_client->dev, "write failed!:%i\n", ret);
+               return ret;
+       }
+       return 0;
+}
+
+EXPORT_SYMBOL(pfuze_reg_write);
+
+int pfuze_reg_rmw(struct mc_pfuze *mc_pfuze, unsigned int offset,
+                 unsigned char mask, unsigned char val)
+{
+       int ret;
+       unsigned char valread;
+       BUG_ON(val & ~mask);
+       ret = pfuze_reg_read(mc_pfuze, offset, &valread);
+       if (ret)
+               return ret;
+       valread = (valread & ~mask) | val;
+       return pfuze_reg_write(mc_pfuze, offset, valread);
+}
+
+EXPORT_SYMBOL(pfuze_reg_rmw);
+
+int pfuze_irq_mask(struct mc_pfuze *mc_pfuze, int irq)
+{
+       int ret;
+       unsigned int offmask = PFUZE_REG_INT_MASK0 + 3 * (irq / 8);
+       unsigned char irqbit = 1 << (irq % 8);
+       unsigned char mask;
+
+       if (irq < 0 || irq >= PFUZE_NUM_IRQ)
+               return -EINVAL;
+
+       ret = pfuze_reg_read(mc_pfuze, offmask, &mask);
+       if (ret)
+               return ret;
+       if (mask & irqbit)
+               /* already masked */
+               return 0;
+       return pfuze_reg_write(mc_pfuze, offmask, mask | irqbit);
+}
+
+EXPORT_SYMBOL(pfuze_irq_mask);
+
+int pfuze_irq_unmask(struct mc_pfuze *mc_pfuze, int irq)
+{
+       int ret;
+       unsigned int offmask = PFUZE_REG_INT_MASK0 + 3 * (irq / 8);
+       unsigned char irqbit = 1 << (irq % 8);
+       unsigned char mask;
+
+       if (irq < 0 || irq >= PFUZE_NUM_IRQ)
+               return -EINVAL;
+
+       ret = pfuze_reg_read(mc_pfuze, offmask, &mask);
+       if (ret)
+               return ret;
+       if (!(mask & irqbit))
+               /* already masked */
+               return 0;
+       return pfuze_reg_write(mc_pfuze, offmask, mask & ~irqbit);
+}
+
+EXPORT_SYMBOL(pfuze_irq_unmask);
+
+int pfuze_irq_status(struct mc_pfuze *mc_pfuze, int irq, int *enabled,
+                    int *pending)
+{
+       int ret;
+       unsigned int offmask = PFUZE_REG_INT_MASK0 + 3 * (irq / 8);
+       unsigned int offstat = PFUZE_REG_INT_STATUS0 + 3 * (irq / 8);
+       unsigned char irqbit = 1 << (irq % 8);
+
+       if (irq < 0 || irq >= PFUZE_NUM_IRQ)
+               return -EINVAL;
+       if (enabled) {
+               unsigned char mask;
+               ret = pfuze_reg_read(mc_pfuze, offmask, &mask);
+               if (ret)
+                       return ret;
+               *enabled = mask & irqbit;
+       }
+       if (pending) {
+               unsigned char stat;
+               ret = pfuze_reg_read(mc_pfuze, offstat, &stat);
+               if (ret)
+                       return ret;
+               *pending = stat & irqbit;
+       }
+       return 0;
+}
+
+EXPORT_SYMBOL(pfuze_irq_status);
+
+int pfuze_irq_ack(struct mc_pfuze *mc_pfuze, int irq)
+{
+       unsigned int offstat = PFUZE_REG_INT_STATUS0 + 3 * (irq / 8);
+       unsigned char val = 1 << (irq % 8);
+       BUG_ON(irq < 0 || irq >= PFUZE_NUM_IRQ);
+       return pfuze_reg_write(mc_pfuze, offstat, val);
+}
+
+EXPORT_SYMBOL(pfuze_irq_ack);
+
+int pfuze_irq_request_nounmask(struct mc_pfuze *mc_pfuze, int irq,
+                              irq_handler_t handler, const char *name,
+                              void *dev)
+{
+       BUG_ON(!mutex_is_locked(&mc_pfuze->lock));
+       BUG_ON(!handler);
+
+       if (irq < 0 || irq >= PFUZE_NUM_IRQ)
+               return -EINVAL;
+       if (mc_pfuze->irqhandler[irq])
+               return -EBUSY;
+       mc_pfuze->irqhandler[irq] = handler;
+       mc_pfuze->irqdata[irq] = dev;
+
+       return 0;
+}
+
+EXPORT_SYMBOL(pfuze_irq_request_nounmask);
+
+int pfuze_irq_request(struct mc_pfuze *mc_pfuze, int irq,
+                     irq_handler_t handler, const char *name, void *dev)
+{
+       int ret;
+
+       ret = pfuze_irq_request_nounmask(mc_pfuze, irq, handler, name, dev);
+       if (ret)
+               return ret;
+       ret = pfuze_irq_unmask(mc_pfuze, irq);
+       if (ret) {
+               mc_pfuze->irqhandler[irq] = NULL;
+               mc_pfuze->irqdata[irq] = NULL;
+               return ret;
+       }
+       return 0;
+}
+
+EXPORT_SYMBOL(pfuze_irq_request);
+
+int pfuze_irq_free(struct mc_pfuze *mc_pfuze, int irq, void *dev)
+{
+       int ret;
+       BUG_ON(!mutex_is_locked(&mc_pfuze->lock));
+
+       if (irq < 0 || irq >= PFUZE_NUM_IRQ || !mc_pfuze->irqhandler[irq] ||
+           mc_pfuze->irqdata[irq] != dev)
+               return -EINVAL;
+
+       ret = pfuze_irq_mask(mc_pfuze, irq);
+       if (ret)
+               return ret;
+       mc_pfuze->irqhandler[irq] = NULL;
+       mc_pfuze->irqdata[irq] = NULL;
+       return 0;
+}
+
+EXPORT_SYMBOL(pfuze_irq_free);
+
+static inline irqreturn_t pfuze_irqhandler(struct mc_pfuze *mc_pfuze, int irq)
+{
+       return mc_pfuze->irqhandler[irq] (irq, mc_pfuze->irqdata[irq]);
+}
+
+static int pfuze_irq_handle(struct mc_pfuze *mc_pfuze, unsigned int offstat,
+                           unsigned int offmask, int baseirq)
+{
+       unsigned char stat, mask;
+       int ret = pfuze_reg_read(mc_pfuze, offstat, &stat);
+       int num_handled = 0;
+
+       if (ret)
+               return ret;
+       ret = pfuze_reg_read(mc_pfuze, offmask, &mask);
+       if (ret)
+               return ret;
+       while (stat & ~mask) {
+               unsigned char irq = __ffs(stat & ~mask);
+               stat &= ~(1 << irq);
+               if (likely(mc_pfuze->irqhandler[baseirq + irq])) {
+                       irqreturn_t handled;
+                       handled = pfuze_irqhandler(mc_pfuze, baseirq + irq);
+                       if (handled == IRQ_HANDLED)
+                               num_handled++;
+               } else {
+                       dev_err(&mc_pfuze->i2c_client->dev,
+                               "BUG: irq %u but no handler\n", baseirq + irq);
+                       mask |= 1 << irq;
+                       ret = pfuze_reg_write(mc_pfuze, offmask, mask);
+               }
+       }
+       return num_handled;
+}
+
+static irqreturn_t pfuze_irq_thread(int irq, void *data)
+{
+       struct mc_pfuze *mc_pfuze = data;
+       irqreturn_t ret;
+       int i, handled = 0;
+
+       pfuze_lock(mc_pfuze);
+       for (i = 0; i < 7; i++) {
+               ret = pfuze_irq_handle(mc_pfuze, PFUZE_REG_INT_STATUS0 + 3 * i,
+                                      PFUZE_REG_INT_MASK0 + 3 * i, 8 * i);
+               if (ret > 0)
+                       handled = 1;
+       }
+       pfuze_unlock(mc_pfuze);
+       return IRQ_RETVAL(handled);
+}
+
+static int pfuze_identify(struct mc_pfuze *mc_pfuze, enum pfuze_id *id)
+{
+       unsigned char value;
+       int ret;
+       ret = pfuze_reg_read(mc_pfuze, PFUZE_REG_DEVICE_ID, &value);
+       if (ret)
+               return ret;
+       switch (value & 0x0f) {
+       case 0x0:
+               *id = PFUZE_ID_PFUZE100;
+               break;
+       default:
+               *id = PFUZE_ID_INVALID;
+               dev_warn(&mc_pfuze->i2c_client->dev, "Illegal ID: %x\n", value);
+               break;
+       }
+       ret = pfuze_reg_read(mc_pfuze, PFUZE_REG_REVISION_ID, &value);
+       if (ret)
+               return ret;
+       dev_info(&mc_pfuze->i2c_client->dev, "Full lay: %x ,Metal lay: %x\n",
+                (value & 0xf0) >> 4, value & 0x0f);
+       ret = pfuze_reg_read(mc_pfuze, PFUZE_REG_FAB_ID, &value);
+       if (ret)
+               return ret;
+       dev_info(&mc_pfuze->i2c_client->dev, "FAB: %x ,FIN: %x\n",
+                (value & 0xc) >> 2, value & 0x3);
+       return 0;
+}
+
+static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
+                                               const struct i2c_client *client)
+{
+       while (id->name[0]) {
+               if (strcmp(client->name, id->name) == 0)
+                       return id;
+               id++;
+       }
+       return NULL;
+
+}
+
+static const char *pfuze_get_chipname(struct mc_pfuze *mc_pfuze)
+{
+       const struct i2c_driver *idrv =
+           to_i2c_driver(mc_pfuze->i2c_client->dev.driver);
+       const struct i2c_device_id *devid =
+           i2c_match_id(idrv->id_table, mc_pfuze->i2c_client);
+       if (!devid)
+               return NULL;
+       return pfuze_chipname[devid->driver_data];
+}
+
+unsigned int pfuze_get_flags(struct mc_pfuze *mc_pfuze)
+{
+       struct pfuze_platform_data *pdata =
+           dev_get_platdata(&mc_pfuze->i2c_client->dev);
+       return pdata->flags;
+}
+
+EXPORT_SYMBOL(pfuze_get_flags);
+
+static int pfuze_add_subdevice_pdata(struct mc_pfuze *mc_pfuze,
+                                    const char *format, void *pdata,
+                                    size_t pdata_size)
+{
+       char buf[30];
+       const char *name = pfuze_get_chipname(mc_pfuze);
+       struct mfd_cell cell = {
+               .platform_data = pdata,
+               .data_size = pdata_size,
+       };
+       if (snprintf(buf, sizeof(buf), format, name) > sizeof(buf))
+               return -E2BIG;
+       cell.name = kmemdup(buf, strlen(buf) + 1, GFP_KERNEL);
+       if (!cell.name)
+               return -ENOMEM;
+       return mfd_add_devices(&mc_pfuze->i2c_client->dev, -1, &cell, 1, NULL,
+                              0);
+}
+
+static int pfuze_add_subdevice(struct mc_pfuze *mc_pfuze, const char *format)
+{
+       return pfuze_add_subdevice_pdata(mc_pfuze, format, NULL, 0);
+}
+
+static ssize_t pfuze_show(struct device *dev,
+                         struct device_attribute *attr, char *buf)
+{
+       unsigned char i, value;
+       int offset = PFUZE_NUMREGS;
+       struct i2c_client *client = to_i2c_client(dev);
+       struct mc_pfuze *mc_pfuze = i2c_get_clientdata(client);
+
+       pfuze_lock(mc_pfuze);
+       for (i = 0; i < offset; i++) {
+               pfuze_reg_read(mc_pfuze, i, &value);
+               pr_info("reg%03d: %02x\t\t", i, value);
+       }
+       pfuze_unlock(mc_pfuze);
+       pr_info("\n");
+
+       return 0;
+}
+
+static ssize_t pfuze_store(struct device *dev,
+                          struct device_attribute *attr, const char *buf,
+                          size_t count)
+{
+       unsigned char reg, value;
+       int ret;
+       char *p;
+       struct i2c_client *client = to_i2c_client(dev);
+       struct mc_pfuze *mc_pfuze = i2c_get_clientdata(client);
+
+       reg = simple_strtoul(buf, NULL, 10);
+
+       p = NULL;
+       p = memchr(buf, ' ', count);
+
+       if (p == NULL) {
+               pfuze_lock(mc_pfuze);
+               pfuze_reg_read(mc_pfuze, reg, &value);
+               pfuze_unlock(mc_pfuze);
+               pr_debug("reg%03d: %02x\n", reg, value);
+               return count;
+       }
+
+       p += 1;
+
+       value = simple_strtoul(p, NULL, 16);
+       pfuze_lock(mc_pfuze);
+       ret = pfuze_reg_write(mc_pfuze, reg, value);
+       if (ret == 0)
+               pr_debug("write reg%03d: %02x\n", reg, value);
+       else
+               pr_debug("register update failed\n");
+
+       pfuze_unlock(mc_pfuze);
+       return count;
+}
+
+static struct device_attribute pfuze_dev_attr = {
+       .attr = {
+                .name = "pfuze_ctl",
+                .mode = S_IRUSR | S_IWUSR,
+                },
+       .show = pfuze_show,
+       .store = pfuze_store,
+};
+
+static int pfuze_probe(struct i2c_client *client,
+                      const struct i2c_device_id *id)
+{
+       struct mc_pfuze *mc_pfuze;
+       struct pfuze_platform_data *pdata = client->dev.platform_data;
+       int ret, i;
+       enum pfuze_id pfuze_id;
+       mc_pfuze = kzalloc(sizeof(*mc_pfuze), GFP_KERNEL);
+       if (!mc_pfuze)
+               return -ENOMEM;
+       i2c_set_clientdata(client, mc_pfuze);
+       mc_pfuze->i2c_client = client;
+
+       mutex_init(&mc_pfuze->lock);
+       pfuze_lock(mc_pfuze);
+       ret = pfuze_identify(mc_pfuze, &pfuze_id);
+       if (ret || pfuze_id == PFUZE_ID_INVALID)
+               goto err_revision;
+       /* mask all of irqs */
+       for (i = 0; i < 7; i++) {
+               ret =
+                   pfuze_reg_write(mc_pfuze, PFUZE_REG_INT_MASK0 + 3 * i,
+                                   0xff);
+               if (ret)
+                       goto err_mask;
+       }
+       ret = request_threaded_irq(client->irq, NULL, pfuze_irq_thread,
+                                  IRQF_ONESHOT | IRQF_TRIGGER_LOW, "pfuze",
+                                  mc_pfuze);
+       if (ret) {
+             err_mask:
+             err_revision:
+               pfuze_unlock(mc_pfuze);
+               dev_set_drvdata(&client->dev, NULL);
+               kfree(mc_pfuze);
+               return ret;
+       }
+       pfuze_unlock(mc_pfuze);
+       if (pdata->flags & PFUZE_USE_REGULATOR) {
+               struct pfuze_regulator_platform_data regulator_pdata = {
+                       .num_regulators = pdata->num_regulators,
+                       .regulators = pdata->regulators,
+               };
+               pfuze_add_subdevice_pdata(mc_pfuze, "%s-regulator",
+                                         &regulator_pdata,
+                                         sizeof(regulator_pdata));
+       }
+       ret = device_create_file(&client->dev, &pfuze_dev_attr);
+       if (ret)
+               dev_err(&client->dev, "create device file failed!\n");
+       return 0;
+}
+
+static int __devexit pfuze_remove(struct i2c_client *client)
+{
+       struct mc_pfuze *mc_pfuze = dev_get_drvdata(&client->dev);
+       free_irq(mc_pfuze->i2c_client->irq, mc_pfuze);
+       mfd_remove_devices(&client->dev);
+       kfree(mc_pfuze);
+       return 0;
+}
+
+static struct i2c_driver pfuze_driver = {
+       .id_table = pfuze_device_id,
+       .driver = {
+                  .name = "mc_pfuze",
+                  .owner = THIS_MODULE,
+                  },
+       .probe = pfuze_probe,
+       .remove = __devexit_p(pfuze_remove),
+};
+
+static int __init pfuze_init(void)
+{
+       return i2c_add_driver(&pfuze_driver);
+}
+
+subsys_initcall(pfuze_init);
+
+static void __exit pfuze_exit(void)
+{
+       i2c_del_driver(&pfuze_driver);
+}
+
+module_exit(pfuze_exit);
+
+MODULE_DESCRIPTION("Core driver for Freescale PFUZE PMIC");
+MODULE_AUTHOR("Freescale Semiconductor, Inc");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mfd/pfuze.h b/include/linux/mfd/pfuze.h
new file mode 100644 (file)
index 0000000..a4c51c5
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef __LINUX_MFD_PFUZE_H
+#define __LINUX_MFD_PFUZE_H
+
+#include <linux/interrupt.h>
+
+struct mc_pfuze;
+void pfuze_lock(struct mc_pfuze *mc_pfuze);
+void pfuze_unlock(struct mc_pfuze *mc_pfuze);
+int pfuze_reg_read(struct mc_pfuze *mc_pfuze, unsigned int offset,
+                  unsigned char *val);
+int pfuze_reg_write(struct mc_pfuze *mc_pfuze, unsigned int offset,
+                   unsigned char val);
+int pfuze_reg_rmw(struct mc_pfuze *mc_pfuze, unsigned int offset,
+                 unsigned char mask, unsigned char val);
+int pfuze_irq_mask(struct mc_pfuze *mc_pfuze, int irq);
+int pfuze_irq_unmask(struct mc_pfuze *mc_pfuze, int irq);
+int pfuze_irq_status(struct mc_pfuze *mc_pfuze, int irq, int *enabled,
+                    int *pending);
+int pfuze_irq_status(struct mc_pfuze *mc_pfuze, int irq, int *enabled,
+                    int *pending);
+int pfuze_irq_ack(struct mc_pfuze *mc_pfuze, int irq);
+int pfuze_irq_request_nounmask(struct mc_pfuze *mc_pfuze, int irq,
+                              irq_handler_t handler, const char *name,
+                              void *dev);
+int pfuze_irq_request(struct mc_pfuze *mc_pfuze, int irq, irq_handler_t handler,
+                     const char *name, void *dev);
+int pfuze_irq_free(struct mc_pfuze *mc_pfuze, int irq, void *dev);
+unsigned int pfuze_get_flags(struct mc_pfuze *mc_pfuze);
+
+#define PFUZE_I2C_RETRY_TIMES   10
+#define PFUZE_NUM_IRQ          56
+#define PFUZE_NUMREGS          128
+#define PFUZE_IRQ_PWRONI       0
+#define PFUZE_IRQ_LOWBATT      1
+#define PFUZE_IRQ_THERM110     2
+#define PFUZE_IRQ_THERM120     3
+#define PFUZE_IRQ_THERM125     4
+#define PFUZE_IRQ_THERM130     5
+#define PFUZE_IRQ_SW1AFAULT    8
+#define PFUZE_IRQ_SW1BFAULT    9
+#define PFUZE_IRQ_SW1CFAULT    10
+#define PFUZE_IRQ_SW2FAULT     11
+#define PFUZE_IRQ_SW3AFAULT    12
+#define PFUZE_IRQ_SW3BFAULT    13
+#define PFUZE_IRQ_SW4FAULT     14
+#define PFUZE_IRQ_SWBSTFAULT   24
+#define PFUZE_IRQ_OTPECC       31
+#define PFUZE_IRQ_VGEN1FAULT   32
+#define PFUZE_IRQ_VGEN2FAULT   33
+#define PFUZE_IRQ_VGEN3FAULT   34
+#define PFUZE_IRQ_VGEN4FAULT   35
+#define PFUZE_IRQ_VGEN5FAULT   36
+#define PFUZE_IRQ_VGEN6FAULT   37
+
+#define PFUZE100_SW1A          0
+#define PFUZE100_SW1B          1
+#define PFUZE100_SW1C          2
+#define PFUZE100_SW2           3
+#define PFUZE100_SW3A          4
+#define PFUZE100_SW3B          5
+#define PFUZE100_SW4           6
+#define PFUZE100_SWBST         7
+#define PFUZE100_VSNVS         8
+#define PFUZE100_VREFDDR       9
+#define PFUZE100_VGEN1         10
+#define PFUZE100_VGEN2         11
+#define PFUZE100_VGEN3         12
+#define PFUZE100_VGEN4         13
+#define PFUZE100_VGEN5         14
+#define PFUZE100_VGEN6         15
+#define PFUZE100_SW2_VOL6      1
+#define PFUZE100_SW3_VOL6      0
+#define PFUZE100_SW4_VOL6      0
+#define PFUZE100_FIRST_VERSION
+
+struct regulator_init_data;
+struct pfuze_regulator_init_data {
+       int id;
+       struct regulator_init_data *init_data;
+};
+
+struct pfuze_regulator_platform_data {
+       int num_regulators;
+       struct pfuze_regulator_init_data *regulators;
+};
+
+struct pfuze_platform_data {
+#define PFUZE_USE_REGULATOR    (1 << 0)
+       unsigned int flags;
+       int num_regulators;
+       struct fuze_regulator_init_data *regulators;
+};
+#endif