From 42d20400c352f724f4dd63b2b52488914b5c0355 Mon Sep 17 00:00:00 2001 From: Robin Gong Date: Mon, 10 Oct 2011 16:34:21 +0800 Subject: [PATCH] ENGR00159530-1 mc34708: add new pmic core driver based on MFD add new mc34708's core driver based on MFD Signed-off-by: Robin Gong --- drivers/mfd/Kconfig | 15 + drivers/mfd/Makefile | 3 +- drivers/mfd/mc-pmic-core.c | 631 ++++++++++++++++++++++++++++++++++++ include/linux/mfd/mc-pmic.h | 143 ++++++++ 4 files changed, 790 insertions(+), 2 deletions(-) create mode 100644 drivers/mfd/mc-pmic-core.c create mode 100644 include/linux/mfd/mc-pmic.h diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index d4cf4bfc8abb..1b43cf6dd3b9 100755 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -507,6 +507,21 @@ config PMIC_DA9053Bx endchoice +config MFD_MC_PMIC + tristate "Support Freescale Freescale's PMIC" + depends on I2C + select MFD_CORE + help + Support for the Freescale's PMIC . + This driver provides common support for accessing the device, + additional drivers must be enabled in order to use the + functionality of the device. +config MFD_MC34708 + tristate "Support for Freescale's PMIC MC34708" + select MFD_MC_PMIC + help + Support for the Freescale's PMIC MC34708 + config PCF50633_ADC tristate "Support for NXP PCF50633 ADC" depends on MFD_PCF50633 diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 1f6b27fc104c..58cace2fea97 100755 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -1,7 +1,6 @@ # # Makefile for multifunction miscellaneous devices # - 88pm860x-objs := 88pm860x-core.o 88pm860x-i2c.o obj-$(CONFIG_MFD_88PM860X) += 88pm860x.o obj-$(CONFIG_MFD_SM501) += sm501.o @@ -42,8 +41,8 @@ obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o 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_CORE) += mfd-core.o diff --git a/drivers/mfd/mc-pmic-core.c b/drivers/mfd/mc-pmic-core.c new file mode 100644 index 000000000000..db46ef1da050 --- /dev/null +++ b/drivers/mfd/mc-pmic-core.c @@ -0,0 +1,631 @@ +/* + * 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 +#include +/*#define VERBOSE_DEBUG*/ +#include +#include +#include +#include +#include +#include +#include + +struct mc_pmic { + struct i2c_client *i2c_client; + struct mutex lock; + int irq; + + irq_handler_t irqhandler[MC_PMIC_NUM_IRQ]; + void *irqdata[MC_PMIC_NUM_IRQ]; +}; + +/*! + * This is the enumeration of versions of PMIC + */ +enum mc_pmic_id { + MC_PMIC_ID_MC34708, + MC_PMIC_ID_INVALID, +}; + +struct mc_version_t { + /*! + * PMIC version identifier. + */ + enum mc_pmic_id id; + /*! + * Revision of the PMIC. + */ + int revision; +}; + +#define PMIC_I2C_RETRY_TIMES 10 + +static const struct i2c_device_id mc_pmic_device_id[] = { + {"mc34708", 0}, + {}, +}; + +static const char *mc_pmic_chipname[] = { + [MC_PMIC_ID_MC34708] = "mc34708", +}; + +void mc_pmic_lock(struct mc_pmic *mc_pmic) +{ + if (!mutex_trylock(&mc_pmic->lock)) { + dev_dbg(&mc_pmic->i2c_client->dev, "wait for %s from %pf\n", + __func__, __builtin_return_address(0)); + + mutex_lock(&mc_pmic->lock); + } + dev_dbg(&mc_pmic->i2c_client->dev, "%s from %pf\n", + __func__, __builtin_return_address(0)); +} + +EXPORT_SYMBOL(mc_pmic_lock); + +void mc_pmic_unlock(struct mc_pmic *mc_pmic) +{ + dev_dbg(&mc_pmic->i2c_client->dev, "%s from %pf\n", + __func__, __builtin_return_address(0)); + mutex_unlock(&mc_pmic->lock); +} + +EXPORT_SYMBOL(mc_pmic_unlock); + +int +mc_pmic_i2c_24bit_read(struct i2c_client *client, unsigned int offset, + unsigned int *value) +{ + unsigned char buf[3]; + int ret; + int i; + + memset(buf, 0, 3); + for (i = 0; i < PMIC_I2C_RETRY_TIMES; i++) { + ret = i2c_smbus_read_i2c_block_data(client, offset, 3, buf); + if (ret == 3) + break; + msleep(1); + } + + if (ret == 3) { + *value = buf[0] << 16 | buf[1] << 8 | buf[2]; + return ret; + } else { + dev_err(&client->dev, "24bit read error, ret = %d\n", ret); + return -1; /* return -1 on failure */ + } +} + +int mc_pmic_reg_read(struct mc_pmic *mc_pmic, unsigned int offset, u32 * val) +{ + BUG_ON(!mutex_is_locked(&mc_pmic->lock)); + + if (offset > MC_PMIC_NUMREGS) + return -EINVAL; + + if (mc_pmic_i2c_24bit_read(mc_pmic->i2c_client, offset, val) == -1) + return -1; + *val &= 0xffffff; + + dev_vdbg(&mc_pmic->i2c_client->dev, "mc_pmic read [%02d] -> 0x%06x\n", + offset, *val); + + return 0; +} + +EXPORT_SYMBOL(mc_pmic_reg_read); +int +mc_pmic_i2c_24bit_write(struct i2c_client *client, + unsigned int offset, unsigned int reg_val) +{ + char buf[3]; + int ret; + int i; + + buf[0] = (reg_val >> 16) & 0xff; + buf[1] = (reg_val >> 8) & 0xff; + buf[2] = (reg_val) & 0xff; + + for (i = 0; i < PMIC_I2C_RETRY_TIMES; i++) { + ret = i2c_smbus_write_i2c_block_data(client, offset, 3, buf); + if (ret == 0) + break; + msleep(1); + } + if (i == PMIC_I2C_RETRY_TIMES) + dev_err(&client->dev, "24bit write error, ret = %d\n", ret); + + return ret; +} + +int mc_pmic_reg_write(struct mc_pmic *mc_pmic, unsigned int offset, u32 val) +{ + BUG_ON(!mutex_is_locked(&mc_pmic->lock)); + + if (offset > MC_PMIC_NUMREGS) + return -EINVAL; + + if (mc_pmic_i2c_24bit_write(mc_pmic->i2c_client, offset, val)) + return -1; + val &= 0xffffff; + + dev_vdbg(&mc_pmic->i2c_client->dev, "mc_pmic write[%02d] -> 0x%06x\n", + offset, val); + + return 0; +} + +EXPORT_SYMBOL(mc_pmic_reg_write); + +int +mc_pmic_reg_rmw(struct mc_pmic *mc_pmic, unsigned int offset, u32 mask, u32 val) +{ + int ret; + u32 valread; + + BUG_ON(val & ~mask); + + ret = mc_pmic_reg_read(mc_pmic, offset, &valread); + if (ret) + return ret; + + valread = (valread & ~mask) | val; + + return mc_pmic_reg_write(mc_pmic, offset, valread); +} + +EXPORT_SYMBOL(mc_pmic_reg_rmw); + +int mc_pmic_irq_mask(struct mc_pmic *mc_pmic, int irq) +{ + int ret; + unsigned int offmask = + irq < 24 ? MC_PMIC_REG_INT_MASK0 : MC_PMIC_REG_INT_MASK1; + u32 irqbit = 1 << (irq < 24 ? irq : irq - 24); + u32 mask; + + if (irq < 0 || irq >= MC_PMIC_NUM_IRQ) + return -EINVAL; + + ret = mc_pmic_reg_read(mc_pmic, offmask, &mask); + if (ret) + return ret; + + if (mask & irqbit) + /* already masked */ + return 0; + + return mc_pmic_reg_write(mc_pmic, offmask, mask | irqbit); +} + +EXPORT_SYMBOL(mc_pmic_irq_mask); + +int mc_pmic_irq_unmask(struct mc_pmic *mc_pmic, int irq) +{ + int ret; + unsigned int offmask = + irq < 24 ? MC_PMIC_REG_INT_MASK0 : MC_PMIC_REG_INT_MASK1; + u32 irqbit = 1 << (irq < 24 ? irq : irq - 24); + u32 mask; + + if (irq < 0 || irq >= MC_PMIC_NUM_IRQ) + return -EINVAL; + + ret = mc_pmic_reg_read(mc_pmic, offmask, &mask); + if (ret) + return ret; + + if (!(mask & irqbit)) + /* already unmasked */ + return 0; + + return mc_pmic_reg_write(mc_pmic, offmask, mask & ~irqbit); +} + +EXPORT_SYMBOL(mc_pmic_irq_unmask); + +int +mc_pmic_irq_status(struct mc_pmic *mc_pmic, int irq, int *enabled, int *pending) +{ + int ret; + unsigned int offmask = + irq < 24 ? MC_PMIC_REG_INT_MASK0 : MC_PMIC_REG_INT_MASK1; + unsigned int offstat = + irq < 24 ? MC_PMIC_REG_INT_STATUS0 : MC_PMIC_REG_INT_STATUS1; + u32 irqbit = 1 << (irq < 24 ? irq : irq - 24); + + if (irq < 0 || irq >= MC_PMIC_NUM_IRQ) + return -EINVAL; + + if (enabled) { + u32 mask; + + ret = mc_pmic_reg_read(mc_pmic, offmask, &mask); + if (ret) + return ret; + + *enabled = mask & irqbit; + } + + if (pending) { + u32 stat; + + ret = mc_pmic_reg_read(mc_pmic, offstat, &stat); + if (ret) + return ret; + + *pending = stat & irqbit; + } + + return 0; +} + +EXPORT_SYMBOL(mc_pmic_irq_status); + +int mc_pmic_irq_ack(struct mc_pmic *mc_pmic, int irq) +{ + unsigned int offstat = + irq < 24 ? MC_PMIC_REG_INT_STATUS0 : MC_PMIC_REG_INT_STATUS1; + unsigned int val = 1 << (irq < 24 ? irq : irq - 24); + + BUG_ON(irq < 0 || irq >= MC_PMIC_NUM_IRQ); + + return mc_pmic_reg_write(mc_pmic, offstat, val); +} + +EXPORT_SYMBOL(mc_pmic_irq_ack); + +int +mc_pmic_irq_request_nounmask(struct mc_pmic *mc_pmic, int irq, + irq_handler_t handler, const char *name, void *dev) +{ + BUG_ON(!mutex_is_locked(&mc_pmic->lock)); + BUG_ON(!handler); + + if (irq < 0 || irq >= MC_PMIC_NUM_IRQ) + return -EINVAL; + + if (mc_pmic->irqhandler[irq]) + return -EBUSY; + + mc_pmic->irqhandler[irq] = handler; + mc_pmic->irqdata[irq] = dev; + + return 0; +} + +EXPORT_SYMBOL(mc_pmic_irq_request_nounmask); + +int +mc_pmic_irq_request(struct mc_pmic *mc_pmic, int irq, + irq_handler_t handler, const char *name, void *dev) +{ + int ret; + + ret = mc_pmic_irq_request_nounmask(mc_pmic, irq, handler, name, dev); + if (ret) + return ret; + + ret = mc_pmic_irq_unmask(mc_pmic, irq); + if (ret) { + mc_pmic->irqhandler[irq] = NULL; + mc_pmic->irqdata[irq] = NULL; + return ret; + } + + return 0; +} + +EXPORT_SYMBOL(mc_pmic_irq_request); + +int mc_pmic_irq_free(struct mc_pmic *mc_pmic, int irq, void *dev) +{ + int ret; + BUG_ON(!mutex_is_locked(&mc_pmic->lock)); + + if (irq < 0 || irq >= MC_PMIC_NUM_IRQ || !mc_pmic->irqhandler[irq] || + mc_pmic->irqdata[irq] != dev) + return -EINVAL; + + ret = mc_pmic_irq_mask(mc_pmic, irq); + if (ret) + return ret; + + mc_pmic->irqhandler[irq] = NULL; + mc_pmic->irqdata[irq] = NULL; + + return 0; +} + +EXPORT_SYMBOL(mc_pmic_irq_free); + +static inline irqreturn_t mc_pmic_irqhandler(struct mc_pmic *mc_pmic, int irq) +{ + return mc_pmic->irqhandler[irq] (irq, mc_pmic->irqdata[irq]); +} + +/* + * returns: number of handled irqs or negative error + * locking: holds mc_pmic->lock + */ +static int +mc_pmic_irq_handle(struct mc_pmic *mc_pmic, + unsigned int offstat, unsigned int offmask, int baseirq) +{ + u32 stat, mask; + int ret = mc_pmic_reg_read(mc_pmic, offstat, &stat); + int num_handled = 0; + + if (ret) + return ret; + + ret = mc_pmic_reg_read(mc_pmic, offmask, &mask); + if (ret) + return ret; + + while (stat & ~mask) { + int irq = __ffs(stat & ~mask); + + stat &= ~(1 << irq); + + if (likely(mc_pmic->irqhandler[baseirq + irq])) { + irqreturn_t handled; + + handled = mc_pmic_irqhandler(mc_pmic, baseirq + irq); + if (handled == IRQ_HANDLED) + num_handled++; + } else { + dev_err(&mc_pmic->i2c_client->dev, + "BUG: irq %u but no handler\n", baseirq + irq); + + mask |= 1 << irq; + + ret = mc_pmic_reg_write(mc_pmic, offmask, mask); + } + } + + return num_handled; +} + +static irqreturn_t mc_pmic_irq_thread(int irq, void *data) +{ + struct mc_pmic *mc_pmic = data; + irqreturn_t ret; + int handled = 0; + + mc_pmic_lock(mc_pmic); + + ret = mc_pmic_irq_handle(mc_pmic, MC_PMIC_REG_INT_STATUS0, + MC_PMIC_REG_INT_MASK0, 0); + if (ret > 0) + handled = 1; + + ret = mc_pmic_irq_handle(mc_pmic, MC_PMIC_REG_INT_STATUS1, + MC_PMIC_REG_INT_MASK1, 24); + if (ret > 0) + handled = 1; + + mc_pmic_unlock(mc_pmic); + + return IRQ_RETVAL(handled); +} + +#define maskval(reg, mask) (((reg) & (mask)) >> __ffs(mask)) +static int mc_pmic_identify(struct mc_pmic *mc_pmic, struct mc_version_t * ver) +{ + + int rev_id = 0; + int rev1 = 0; + int rev2 = 0; + int finid = 0; + int icid = 0; + int ret; + ret = mc_pmic_reg_read(mc_pmic, MC_PMIC_REG_IDENTIFICATION, &rev_id); + if (ret) { + dev_dbg(&mc_pmic->i2c_client->dev, "read ID error!%x\n", ret); + return ret; + } + rev1 = (rev_id & 0x018) >> 3; + rev2 = (rev_id & 0x007); + icid = (rev_id & 0x01C0) >> 6; + finid = (rev_id & 0x01E00) >> 9; + ver->id = MC_PMIC_ID_MC34708; + + ver->revision = ((rev1 * 10) + rev2); + dev_dbg(&mc_pmic->i2c_client->dev, + "mc_pmic Rev %d.%d FinVer %x detected\n", rev1, rev2, finid); + 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 struct i2c_device_id *i2c_get_device_id(const struct i2c_client + *idev) +{ + const struct i2c_driver *idrv = to_i2c_driver(idev->dev.driver); + + return i2c_match_id(idrv->id_table, idev); +} + +static const char *mc_pmic_get_chipname(struct mc_pmic *mc_pmic) +{ + const struct i2c_device_id *devid = + i2c_get_device_id(mc_pmic->i2c_client); + + if (!devid) + return NULL; + + return mc_pmic_chipname[devid->driver_data]; +} + +int mc_pmic_get_flags(struct mc_pmic *mc_pmic) +{ + struct mc_pmic_platform_data *pdata = + dev_get_platdata(&mc_pmic->i2c_client->dev); + + return pdata->flags; +} + +EXPORT_SYMBOL(mc_pmic_get_flags); + +static int +mc_pmic_add_subdevice_pdata(struct mc_pmic *mc_pmic, + const char *format, void *pdata, size_t pdata_size) +{ + char buf[30]; + const char *name = mc_pmic_get_chipname(mc_pmic); + + struct mfd_cell cell = { + .platform_data = pdata, + .data_size = pdata_size, + }; + + /* there is no asnprintf in the kernel :-( */ + 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_pmic->i2c_client->dev, -1, &cell, 1, NULL, + 0); +} + +static int mc_pmic_add_subdevice(struct mc_pmic *mc_pmic, const char *format) +{ + return mc_pmic_add_subdevice_pdata(mc_pmic, format, NULL, 0); +} + +static int +mc_pmic_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct mc_pmic *mc_pmic; + struct mc_version_t version; + struct mc_pmic_platform_data *pdata = client->dev.platform_data; + int ret; + mc_pmic = kzalloc(sizeof(*mc_pmic), GFP_KERNEL); + if (!mc_pmic) + return -ENOMEM; + i2c_set_clientdata(client, mc_pmic); + mc_pmic->i2c_client = client; + + mutex_init(&mc_pmic->lock); + mc_pmic_lock(mc_pmic); + mc_pmic_identify(mc_pmic, &version); + /* mask all irqs */ + ret = mc_pmic_reg_write(mc_pmic, MC_PMIC_REG_INT_MASK0, 0x00ffffff); + if (ret) + goto err_mask; + + ret = mc_pmic_reg_write(mc_pmic, MC_PMIC_REG_INT_MASK1, 0x00ffffff); + if (ret) + goto err_mask; + + ret = request_threaded_irq(client->irq, NULL, mc_pmic_irq_thread, + IRQF_ONESHOT | IRQF_TRIGGER_HIGH, "mc_pmic", + mc_pmic); + + if (ret) { + err_mask: + err_revision: + mc_pmic_unlock(mc_pmic); + dev_set_drvdata(&client->dev, NULL); + kfree(mc_pmic); + return ret; + } + + mc_pmic_unlock(mc_pmic); + + if (pdata->flags & MC_PMIC_USE_ADC) + mc_pmic_add_subdevice(mc_pmic, "%s-adc"); + + + if (pdata->flags & MC_PMIC_USE_REGULATOR) { + struct mc_pmic_regulator_platform_data regulator_pdata = { + .num_regulators = pdata->num_regulators, + .regulators = pdata->regulators, + }; + + mc_pmic_add_subdevice_pdata(mc_pmic, "%s-regulator", + ®ulator_pdata, + sizeof(regulator_pdata)); + } + + if (pdata->flags & MC_PMIC_USE_RTC) + mc_pmic_add_subdevice(mc_pmic, "%s-rtc"); + + if (pdata->flags & MC_PMIC_USE_TOUCHSCREEN) + mc_pmic_add_subdevice(mc_pmic, "%s-ts"); + + return 0; +} + +static int __devexit mc_pmic_remove(struct i2c_client *client) +{ + struct mc_pmic *mc_pmic = dev_get_drvdata(&client->dev); + + free_irq(mc_pmic->i2c_client->irq, mc_pmic); + + mfd_remove_devices(&client->dev); + + kfree(mc_pmic); + + return 0; +} + +static struct i2c_driver mc_pmic_driver = { + .id_table = mc_pmic_device_id, + .driver = { + .name = "mc_pmic", + .owner = THIS_MODULE, + }, + .probe = mc_pmic_probe, + .remove = __devexit_p(mc_pmic_remove), +}; + +static int __init mc_pmic_init(void) +{ + return i2c_add_driver(&mc_pmic_driver); +} + +subsys_initcall(mc_pmic_init); + +static void __exit mc_pmic_exit(void) +{ + i2c_del_driver(&mc_pmic_driver); +} + +module_exit(mc_pmic_exit); + +MODULE_DESCRIPTION("Core driver for Freescale MC34708 PMIC"); +MODULE_AUTHOR("Freescale Semiconductor, Inc"); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/mfd/mc-pmic.h b/include/linux/mfd/mc-pmic.h new file mode 100644 index 000000000000..2256913b094b --- /dev/null +++ b/include/linux/mfd/mc-pmic.h @@ -0,0 +1,143 @@ +/* For mc34708's pmic driver + * Copyright (C) 2004-2011 Freescale Semiconductor, Inc. + * + * based on: + * Copyright 2009-2010 Pengutronix, Uwe Kleine-Koenig + * + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License version 2 as published by the + * Free Software Foundation. + */ +#ifndef __LINUX_MFD_MC_PMIC_H +#define __LINUX_MFD_MC_PMIC_H + +#include + +struct mc_pmic; + +void mc_pmic_lock(struct mc_pmic *mc_pmic); +void mc_pmic_unlock(struct mc_pmic *mc_pmic); + +int mc_pmic_reg_read(struct mc_pmic *mc_pmic, unsigned int offset, u32 * val); +int mc_pmic_reg_write(struct mc_pmic *mc_pmic, unsigned int offset, u32 val); +int mc_pmic_reg_rmw(struct mc_pmic *mc_pmic, unsigned int offset, + u32 mask, u32 val); + +int mc_pmic_get_flags(struct mc_pmic *mc_pmic); + +int mc_pmic_irq_request(struct mc_pmic *mc_pmic, int irq, + irq_handler_t handler, const char *name, void *dev); +int mc_pmic_irq_request_nounmask(struct mc_pmic *mc_pmic, int irq, + irq_handler_t handler, const char *name, + void *dev); +int mc_pmic_irq_free(struct mc_pmic *mc_pmic, int irq, void *dev); + +int mc_pmic_irq_mask(struct mc_pmic *mc_pmic, int irq); +int mc_pmic_irq_unmask(struct mc_pmic *mc_pmic, int irq); +int mc_pmic_irq_status(struct mc_pmic *mc_pmic, int irq, + int *enabled, int *pending); +int mc_pmic_irq_ack(struct mc_pmic *mc_pmic, int irq); + +int mc_pmic_get_flags(struct mc_pmic *mc_pmic); + +#ifdef CONFIG_MFD_MC34708 +#define MC34708_SW1A 0 +#define MC34708_SW1B 1 +#define MC34708_SW2 2 +#define MC34708_SW3 3 +#define MC34708_SW4A 4 +#define MC34708_SW4B 5 +#define MC34708_SW5 6 +#define MC34708_SWBST 7 +#define MC34708_VPLL 8 +#define MC34708_VREFDDR 9 +#define MC34708_VUSB 10 +#define MC34708_VUSB2 11 +#define MC34708_VDAC 12 +#define MC34708_VGEN1 13 +#define MC34708_VGEN2 14 +#define MC34708_REGU_NUM 15 + +#define MC34708_REG_INT_STATUS0 0 +#define MC34708_REG_INT_MASK0 1 +#define MC34708_REG_INT_STATUS1 3 +#define MC34708_REG_INT_MASK1 4 +#define MC34708_REG_IDENTIFICATION 7 +#define MC_PMIC_REG_INT_MASK0 MC34708_REG_INT_MASK0 +#define MC_PMIC_REG_INT_MASK1 MC34708_REG_INT_MASK1 +#define MC_PMIC_REG_INT_STATUS0 MC34708_REG_INT_STATUS0 +#define MC_PMIC_REG_INT_STATUS1 MC34708_REG_INT_STATUS1 +#define MC_PMIC_REG_IDENTIFICATION MC34708_REG_IDENTIFICATION +#endif + +#define MC_PMIC_IRQ_ADCDONE 0 +#define MC_PMIC_IRQ_TSDONE 1 +#define MC_PMIC_IRQ_TSPENDET 2 +#define MC_PMIC_IRQ_USBDET 3 +#define MC_PMIC_IRQ_AUXDET 4 +#define MC_PMIC_IRQ_USBOVP 5 +#define MC_PMIC_IRQ_AUXOVP 6 +#define MC_PMIC_IRQ_CHRTIMEEXP 7 +#define MC_PMIC_IRQ_BATTOTP 8 +#define MC_PMIC_IRQ_BATTOVP 9 +#define MC_PMIC_IRQ_CHRCMPL 10 +#define MC_PMIC_IRQ_WKVBUSDET 11 +#define MC_PMIC_IRQ_WKAUXDET 12 +#define MC_PMIC_IRQ_LOWBATT 13 +#define MC_PMIC_IRQ_VBUSREGMI 14 +#define MC_PMIC_IRQ_ATTACH 15 +#define MC_PMIC_IRQ_DETACH 16 +#define MC_PMIC_IRQ_KP 17 +#define MC_PMIC_IRQ_LKP 18 +#define MC_PMIC_IRQ_LKR 19 +#define MC_PMIC_IRQ_UKNOW_ATTA 20 +#define MC_PMIC_IRQ_ADC_CHANGE 21 +#define MC_PMIC_IRQ_STUCK_KEY 22 +#define MC_PMIC_IRQ_STUCK_KEY_RCV 23 +#define MC_PMIC_IRQ_1HZ 24 +#define MC_PMIC_IRQ_TODA 25 +#define MC_PMIC_IRQ_UNUSED1 26 +#define MC_PMIC_IRQ_PWRON1 27 +#define MC_PMIC_IRQ_PWRON2 28 +#define MC_PMIC_IRQ_WDIRESET 29 +#define MC_PMIC_IRQ_SYSRST 30 +#define MC_PMIC_IRQ_RTCRST 31 +#define MC_PMIC_IRQ_PCI 32 +#define MC_PMIC_IRQ_WARM 33 +#define MC_PMIC_IRQ_MEMHLD 34 +#define MC_PMIC_IRQ_UNUSED2 35 +#define MC_PMIC_IRQ_THWARNL 36 +#define MC_PMIC_IRQ_THWARNH 37 +#define MC_PMIC_IRQ_CLK 38 +#define MC_PMIC_IRQ_UNUSED3 39 +#define MC_PMIC_IRQ_SCP 40 +#define MC_PMIC_NUMREGS 0x3f +#define MC_PMIC_NUM_IRQ 46 + +struct regulator_init_data; + +struct mc_pmic_regulator_init_data { + int id; + struct regulator_init_data *init_data; +}; + +struct mc_pmic_regulator_platform_data { + int num_regulators; + struct mc_pmic_regulator_init_data *regulators; +}; + +struct mc_pmic_platform_data { +#define MC_PMIC_USE_TOUCHSCREEN (1 << 0) +#define MC_PMIC_USE_CODEC (1 << 1) +#define MC_PMIC_USE_ADC (1 << 2) +#define MC_PMIC_USE_RTC (1 << 3) +#define MC_PMIC_USE_REGULATOR (1 << 4) +#define MC_PMIC_USE_LED (1 << 5) + unsigned int flags; + + int num_regulators; + struct mc_pmic_regulator_init_data *regulators; +}; + +#endif /* ifndef __LINUX_MFD_MC_PMIC_H */ -- 2.39.5