Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755856Ab1CHGMZ (ORCPT ); Tue, 8 Mar 2011 01:12:25 -0500 Received: from wolverine01.qualcomm.com ([199.106.114.254]:30682 "EHLO wolverine01.qualcomm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752679Ab1CHGLd (ORCPT ); Tue, 8 Mar 2011 01:11:33 -0500 X-IronPort-AV: E=McAfee;i="5400,1158,6278"; a="78610003" From: adharmap@codeaurora.org To: davidb@codeaurora.org Cc: "David S. Miller" , Abhijeet Dharmapurikar , Andrew Morton , Bryan Huntsman , Daniel Walker , David Collins , Grant Likely , Greg Kroah-Hartman , Joe Perches , Russell King , Samuel Ortiz , Stepan Moskovchenko , Mark Brown , Linus Walleij , Thomas Glexiner , linux-arm-kernel@lists.infradead.org, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [Qualcomm PM8921 MFD v2 4/6] mfd: pm8xxx-mpp: Add pm8xxx MPP driver Date: Mon, 7 Mar 2011 22:09:48 -0800 Message-Id: <1299564590-30116-5-git-send-email-adharmap@codeaurora.org> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1299564590-30116-1-git-send-email-adharmap@codeaurora.org> References: <1299564590-30116-1-git-send-email-adharmap@codeaurora.org> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 21349 Lines: 715 From: David Collins Add support for multi-purpose pins (MPPs) on Qualcomm PM8xxx PMIC chips. PM8xxx MPPs can be configured as digital or analog inputs or outputs, current sinks, or buffers. Signed-off-by: David Collins --- drivers/mfd/Kconfig | 8 + drivers/mfd/Makefile | 1 + drivers/mfd/pm8921-core.c | 31 ++++ drivers/mfd/pm8xxx-mpp.c | 320 ++++++++++++++++++++++++++++++++++++++++ include/linux/mfd/pm8921.h | 9 +- include/linux/mfd/pm8xxx/mpp.h | 233 +++++++++++++++++++++++++++++ 6 files changed, 601 insertions(+), 1 deletions(-) create mode 100644 drivers/mfd/pm8xxx-mpp.c create mode 100644 include/linux/mfd/pm8xxx/mpp.h diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 318e42a..0000dac 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -652,6 +652,14 @@ config MFD_PM8XXX_IRQ This is required to use certain other PM 8xxx features, such as GPIO and MPP. +config MFD_PM8XXX_MPP + tristate "Support for Qualcomm PM8xxx MPP features" + depends on MFD_PM8XXX + default y if MFD_PM8XXX + help + This is the multi-purpose pin (MPP) driver for Qualcomm PM 8xxx PMIC + chips. + endif # MFD_SUPPORT menu "Multimedia Capabilities Port drivers" diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 5fc9315..8891177 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -85,3 +85,4 @@ obj-$(CONFIG_MFD_WL1273_CORE) += wl1273-core.o obj-$(CONFIG_MFD_CS5535) += cs5535-mfd.o obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o obj-$(CONFIG_MFD_PM8XXX_IRQ) += pm8xxx-irq.o +obj-$(CONFIG_MFD_PM8XXX_MPP) += pm8xxx-mpp.o diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c index c887ac6..e9411fc 100644 --- a/drivers/mfd/pm8921-core.c +++ b/drivers/mfd/pm8921-core.c @@ -24,6 +24,8 @@ #define REG_HWREV 0x002 /* PMIC4 revision */ #define REG_HWREV_2 0x0E8 /* PMIC4 revision 2 */ +#define REG_MPP_BASE 0x050 + struct pm8921 { struct device *dev; void *irq_data; @@ -95,6 +97,22 @@ static struct mfd_cell gpio_cell __devinitdata = { .num_resources = ARRAY_SIZE(gpio_cell_resources), }; +static const struct resource mpp_cell_resources[] __devinitconst = { + { + .start = PM8921_IRQ_BLOCK_BIT(PM8921_MPP_BLOCK_START, 0), + .end = PM8921_IRQ_BLOCK_BIT(PM8921_MPP_BLOCK_START, 0) + + PM8921_NR_MPPS - 1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct mfd_cell mpp_cell __devinitdata = { + .name = PM8XXX_MPP_DEV_NAME, + .id = -1, + .resources = mpp_cell_resources, + .num_resources = ARRAY_SIZE(mpp_cell_resources), +}; + static int __devinit pm8921_add_subdevices(const struct pm8921_platform_data *pdata, struct pm8921 *pmic, @@ -132,6 +150,19 @@ static int __devinit pm8921_add_subdevices(const struct pm8921_platform_data } } + if (pdata->mpp_pdata) { + pdata->mpp_pdata->core_data.nmpps = PM8921_NR_MPPS; + pdata->mpp_pdata->core_data.base_addr = REG_MPP_BASE; + mpp_cell.platform_data = pdata->mpp_pdata; + mpp_cell.data_size = sizeof(struct pm8xxx_mpp_platform_data); + ret = mfd_add_devices(pmic->dev, 0, &mpp_cell, 1, NULL, + irq_base); + if (ret) { + pr_err("Failed to add mpp subdevice ret=%d\n", ret); + goto bail; + } + } + return 0; bail: if (pmic->irq_data) { diff --git a/drivers/mfd/pm8xxx-mpp.c b/drivers/mfd/pm8xxx-mpp.c new file mode 100644 index 0000000..174294a --- /dev/null +++ b/drivers/mfd/pm8xxx-mpp.c @@ -0,0 +1,320 @@ +/* Copyright (c) 2011, Code Aurora Forum. 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 version 2 and + * only version 2 as published by the Free Software Foundation. + * + * 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. + */ +/* + * Qualcomm PM8XXX Multi-Purpose Pin (MPP) driver + * + */ + +#define pr_fmt(fmt) "%s: " fmt, __func__ + +#include +#include +#include +#include +#include +#include + +/* MPP Type */ +#define PM8XXX_MPP_TYPE_MASK 0xE0 +#define PM8XXX_MPP_TYPE_SHIFT 5 + +/* MPP Config Level */ +#define PM8XXX_MPP_CONFIG_LVL_MASK 0x1C +#define PM8XXX_MPP_CONFIG_LVL_SHIFT 2 + +/* MPP Config Control */ +#define PM8XXX_MPP_CONFIG_CTRL_MASK 0x03 +#define PM8XXX_MPP_CONFIG_CTRL_SHIFT 0 + +struct pm8xxx_mpp_chip { + struct list_head link; + struct gpio_chip gpio_chip; + struct mutex pm_lock; + u8 *ctrl_reg; + int mpp_base; + int irq_base; + int nmpps; + u16 base_addr; +}; + +static LIST_HEAD(pm8xxx_mpp_chips); + +static int pm8xxx_mpp_write(struct pm8xxx_mpp_chip *mpp_chip, u16 offset, + u8 val, u8 mask) +{ + u8 reg; + int rc; + + mutex_lock(&mpp_chip->pm_lock); + + reg = (mpp_chip->ctrl_reg[offset] & ~mask) | (val & mask); + rc = pm8xxx_writeb(mpp_chip->gpio_chip.dev->parent, + mpp_chip->base_addr + offset, reg); + if (!rc) + mpp_chip->ctrl_reg[offset] = reg; + + mutex_unlock(&mpp_chip->pm_lock); + + return rc; +} + +static int pm8xxx_mpp_to_irq(struct gpio_chip *chip, unsigned offset) +{ + struct pm8xxx_mpp_chip *mpp_chip = dev_get_drvdata(chip->dev); + + return mpp_chip->irq_base + offset; +} + +static int pm8xxx_mpp_get(struct gpio_chip *chip, unsigned offset) +{ + struct pm8xxx_mpp_chip *mpp_chip = dev_get_drvdata(chip->dev); + int rc; + + if ((mpp_chip->ctrl_reg[offset] & PM8XXX_MPP_TYPE_MASK) >> + PM8XXX_MPP_TYPE_SHIFT == PM8XXX_MPP_TYPE_D_OUTPUT) + rc = mpp_chip->ctrl_reg[offset] & PM8XXX_MPP_CONFIG_CTRL_MASK; + else + rc = pm8xxx_read_irq_stat(mpp_chip->gpio_chip.dev->parent, + mpp_chip->irq_base + offset); + + return rc; +} + +static void pm8xxx_mpp_set(struct gpio_chip *chip, unsigned offset, int val) +{ + struct pm8xxx_mpp_chip *mpp_chip = dev_get_drvdata(chip->dev); + u8 reg = val ? PM8XXX_MPP_DOUT_CTRL_HIGH : PM8XXX_MPP_DOUT_CTRL_LOW; + int rc; + + rc = pm8xxx_mpp_write(mpp_chip, offset, reg, + PM8XXX_MPP_CONFIG_CTRL_MASK); + if (rc) + pr_err("pm8xxx_mpp_write(): rc=%d\n", rc); +} + +static int pm8xxx_mpp_dir_input(struct gpio_chip *chip, unsigned offset) +{ + struct pm8xxx_mpp_chip *mpp_chip = dev_get_drvdata(chip->dev); + int rc = pm8xxx_mpp_write(mpp_chip, offset, + PM8XXX_MPP_TYPE_D_INPUT << PM8XXX_MPP_TYPE_SHIFT, + PM8XXX_MPP_TYPE_MASK); + + if (rc) + pr_err("pm8xxx_mpp_write(): rc=%d\n", rc); + return rc; +} + +static int pm8xxx_mpp_dir_output(struct gpio_chip *chip, + unsigned offset, int val) +{ + struct pm8xxx_mpp_chip *mpp_chip = dev_get_drvdata(chip->dev); + u8 reg = (PM8XXX_MPP_TYPE_D_OUTPUT << PM8XXX_MPP_TYPE_SHIFT) | + (val & PM8XXX_MPP_CONFIG_CTRL_MASK); + u8 mask = PM8XXX_MPP_TYPE_MASK | PM8XXX_MPP_CONFIG_CTRL_MASK; + int rc = pm8xxx_mpp_write(mpp_chip, offset, reg, mask); + + if (rc) + pr_err("pm8xxx_mpp_write(): rc=%d\n", rc); + return rc; +} + +static void pm8xxx_mpp_dbg_show(struct seq_file *s, struct gpio_chip *chip) +{ + static const char * const ctype[] = { "d_in", "d_out", "bi_dir", + "a_in", "a_out", "sink", + "dtest_sink", "dtest_out" + }; + struct pm8xxx_mpp_chip *mpp_chip = dev_get_drvdata(chip->dev); + u8 type, state; + const char *label; + int i; + + for (i = 0; i < mpp_chip->nmpps; i++) { + label = gpiochip_is_requested(chip, i); + type = (mpp_chip->ctrl_reg[i] & PM8XXX_MPP_TYPE_MASK) >> + PM8XXX_MPP_TYPE_SHIFT; + state = pm8xxx_mpp_get(chip, i); + seq_printf(s, "gpio-%-3d (%-12.12s) %-10.10s" + " %s 0x%02x\n", + chip->base + i, + label ? label : "--", + ctype[type], + state ? "hi" : "lo", + mpp_chip->ctrl_reg[i]); + } +} + +int pm8xxx_mpp_config(unsigned mpp, unsigned type, unsigned level, + unsigned control) +{ + struct pm8xxx_mpp_chip *mpp_chip; + int found = 0; + u8 config, mask; + int rc; + + list_for_each_entry(mpp_chip, &pm8xxx_mpp_chips, link) { + if (mpp >= mpp_chip->mpp_base + && mpp < mpp_chip->mpp_base + mpp_chip->nmpps) { + found = 1; + break; + } + } + if (!found) { + pr_err("called on mpp %d not handled by any pmic\n", mpp); + return -EINVAL; + } + + mask = PM8XXX_MPP_TYPE_MASK | PM8XXX_MPP_CONFIG_LVL_MASK | + PM8XXX_MPP_CONFIG_CTRL_MASK; + config = (type << PM8XXX_MPP_TYPE_SHIFT) & PM8XXX_MPP_TYPE_MASK; + config |= (level << PM8XXX_MPP_CONFIG_LVL_SHIFT) & + PM8XXX_MPP_CONFIG_LVL_MASK; + config |= control & PM8XXX_MPP_CONFIG_CTRL_MASK; + + rc = pm8xxx_mpp_write(mpp_chip, mpp - mpp_chip->mpp_base, config, mask); + + if (rc) + pr_err("pm8xxx_mpp_write(): rc=%d\n", rc); + + return rc; +} +EXPORT_SYMBOL(pm8xxx_mpp_config); + +static int __devinit pm8xxx_mpp_reg_init(struct pm8xxx_mpp_chip *mpp_chip) +{ + int rc, i; + + for (i = 0; i < mpp_chip->nmpps; i++) { + rc = pm8xxx_readb(mpp_chip->gpio_chip.dev->parent, + mpp_chip->base_addr + i, + &mpp_chip->ctrl_reg[i]); + if (rc) + goto bail; + } + +bail: + return rc; +} + +static int __devinit pm8xxx_mpp_probe(struct platform_device *pdev) +{ + int rc; + const struct pm8xxx_mpp_platform_data *pdata = pdev->dev.platform_data; + struct pm8xxx_mpp_chip *mpp_chip; + + if (!pdata) { + pr_err("missing platform data\n"); + rc = -EINVAL; + goto out; + } + + mpp_chip = kzalloc(sizeof(struct pm8xxx_mpp_chip), GFP_KERNEL); + if (!mpp_chip) { + pr_err("Cannot allocate %d bytes\n", + sizeof(struct pm8xxx_mpp_chip)); + rc = -ENOMEM; + goto out; + } + + mpp_chip->ctrl_reg = kzalloc(pdata->core_data.nmpps, GFP_KERNEL); + if (!mpp_chip->ctrl_reg) { + pr_err("Cannot allocate %d bytes\n", pdata->core_data.nmpps); + rc = -ENOMEM; + goto free_mpp_chip; + } + + mutex_init(&mpp_chip->pm_lock); + + mpp_chip->gpio_chip.label = PM8XXX_MPP_DEV_NAME; + mpp_chip->gpio_chip.direction_input = pm8xxx_mpp_dir_input; + mpp_chip->gpio_chip.direction_output = pm8xxx_mpp_dir_output; + mpp_chip->gpio_chip.to_irq = pm8xxx_mpp_to_irq; + mpp_chip->gpio_chip.get = pm8xxx_mpp_get; + mpp_chip->gpio_chip.set = pm8xxx_mpp_set; + mpp_chip->gpio_chip.dbg_show = pm8xxx_mpp_dbg_show; + mpp_chip->gpio_chip.ngpio = pdata->core_data.nmpps; + mpp_chip->gpio_chip.can_sleep = 1; + mpp_chip->gpio_chip.dev = &pdev->dev; + mpp_chip->gpio_chip.base = pdata->mpp_base; + mpp_chip->irq_base = platform_get_irq(pdev, 0); + mpp_chip->mpp_base = pdata->mpp_base; + mpp_chip->base_addr = pdata->core_data.base_addr; + mpp_chip->nmpps = pdata->core_data.nmpps; + + list_add(&mpp_chip->link, &pm8xxx_mpp_chips); + platform_set_drvdata(pdev, mpp_chip); + + rc = gpiochip_add(&mpp_chip->gpio_chip); + if (rc) { + pr_err("gpiochip_add failed, rc=%d\n", rc); + goto reset_drvdata; + } + + rc = pm8xxx_mpp_reg_init(mpp_chip); + if (rc) { + pr_err("failed to read MPP ctrl registers, rc=%d\n", rc); + goto remove_chip; + } + + return 0; + +remove_chip: + if (gpiochip_remove(&mpp_chip->gpio_chip)) + pr_err("failed to remove gpio chip\n"); +reset_drvdata: + platform_set_drvdata(pdev, NULL); + mutex_destroy(&mpp_chip->pm_lock); +free_mpp_chip: + kfree(mpp_chip); +out: + return rc; +} + +static int __devexit pm8xxx_mpp_remove(struct platform_device *pdev) +{ + struct pm8xxx_mpp_chip *mpp_chip = platform_get_drvdata(pdev); + + platform_set_drvdata(pdev, NULL); + if (gpiochip_remove(&mpp_chip->gpio_chip)) + pr_err("failed to remove gpio chip\n"); + mutex_destroy(&mpp_chip->pm_lock); + kfree(mpp_chip->ctrl_reg); + kfree(mpp_chip); + + return 0; +} + +static struct platform_driver pm8xxx_mpp_driver = { + .probe = pm8xxx_mpp_probe, + .remove = __devexit_p(pm8xxx_mpp_remove), + .driver = { + .name = PM8XXX_MPP_DEV_NAME, + .owner = THIS_MODULE, + }, +}; + +static int __init pm8xxx_mpp_init(void) +{ + return platform_driver_register(&pm8xxx_mpp_driver); +} +subsys_initcall(pm8xxx_mpp_init); + +static void __exit pm8xxx_mpp_exit(void) +{ + platform_driver_unregister(&pm8xxx_mpp_driver); +} +module_exit(pm8xxx_mpp_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("PM8XXX MPP driver"); +MODULE_VERSION("1.0"); +MODULE_ALIAS("platform:" PM8XXX_MPP_DEV_NAME); diff --git a/include/linux/mfd/pm8921.h b/include/linux/mfd/pm8921.h index 74d47c7..1867bdb 100644 --- a/include/linux/mfd/pm8921.h +++ b/include/linux/mfd/pm8921.h @@ -20,22 +20,29 @@ #include #include #include +#include #define PM8921_NR_IRQS 256 #define PM8921_NR_GPIOS 44 +#define PM8921_NR_MPPS 12 + #define PM8921_GPIO_BLOCK_START 24 +#define PM8921_MPP_BLOCK_START 16 #define PM8921_IRQ_BLOCK_BIT(block, bit) ((block) * 8 + (bit)) -/* GPIOs [1,N] */ +/* GPIOs and MPPs [1,N] */ #define PM8921_GPIO_IRQ(base, gpio) ((base) + \ PM8921_IRQ_BLOCK_BIT(PM8921_GPIO_BLOCK_START, (gpio)-1)) +#define PM8921_MPP_IRQ(base, mpp) ((base) + \ + PM8921_IRQ_BLOCK_BIT(PM8921_MPP_BLOCK_START, (mpp)-1)) struct pm8921_platform_data { int irq_base; struct pm8xxx_irq_platform_data *irq_pdata; struct pm8xxx_gpio_platform_data *gpio_pdata; + struct pm8xxx_mpp_platform_data *mpp_pdata; }; #endif diff --git a/include/linux/mfd/pm8xxx/mpp.h b/include/linux/mfd/pm8xxx/mpp.h new file mode 100644 index 0000000..c779760 --- /dev/null +++ b/include/linux/mfd/pm8xxx/mpp.h @@ -0,0 +1,233 @@ +/* Copyright (c) 2011, Code Aurora Forum. 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 version 2 and + * only version 2 as published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __PM8XXX_MPP_H +#define __PM8XXX_MPP_H + +#include + +#define PM8XXX_MPP_DEV_NAME "pm8xxx-mpp" + +struct pm8xxx_mpp_core_data { + int base_addr; + int nmpps; +}; + +struct pm8xxx_mpp_platform_data { + struct pm8xxx_mpp_core_data core_data; + int mpp_base; +}; + +/* API */ +#if defined(CONFIG_MFD_PM8XXX_MPP) || defined(CONFIG_MFD_PM8XXX_MPP_MODULE) + +/** + * pm8xxx_mpp_config() - configure control options of a multi-purpose pin (MPP) + * @mpp: global GPIO number corresponding to the MPP + * @type: MPP type which determines the overall MPP function (i.e. digital + * in/out/bi, analog in/out, current sink, or test). It should be + * set to the value of one of PM8XXX_MPP_TYPE_D_*. + * @level: meaning depends upon MPP type specified + * @control: meaning depends upon MPP type specified + * Context: can sleep + * + * RETURNS: an appropriate -ERRNO error value on error, or zero for success. + * + * Usage of level argument: + * 1. type = PM8XXX_MPP_TYPE_D_INPUT, PM8XXX_MPP_TYPE_D_OUTPUT, + * PM8XXX_MPP_TYPE_D_BI_DIR, or PM8XXX_MPP_TYPE_DTEST_OUTPUT - + * + * level specifies that digital logic level to use for the MPP. It should + * be set to the value of one of PM8XXX_MPP_DIG_LEVEL_*. Actual regulator + * connections for these level choices are PMIC chip specific. + * + * 2. type = PM8XXX_MPP_TYPE_A_INPUT - + * + * level specifies where in the PMIC chip the analog input value should + * be routed to. It should be set to the value of one of + * PM8XXX_MPP_AIN_AMUX_*. + * + * 3. type = PM8XXX_MPP_TYPE_A_OUTPUT - + * + * level specifies the output analog voltage reference level. It should + * be set to the value of one of PM8XXX_MPP_AOUT_LVL_*. + * + * 4. type = PM8XXX_MPP_TYPE_SINK or PM8XXX_MPP_TYPE_DTEST_SINK - + * + * level specifies the output current level. It should be set to the value + * of one of PM8XXX_MPP_CS_OUT_*. + * + * Usage of control argument: + * 1. type = PM8XXX_MPP_TYPE_D_INPUT - + * + * control specifies how the digital input should be routed in the chip. + * It should be set to the value of one of PM8XXX_MPP_DIN_TO_*. + * + * 2. type = PM8XXX_MPP_TYPE_D_OUTPUT - + * + * control specifies the digital output value. It should be set to the + * value of one of PM8XXX_MPP_DOUT_CTRL_*. + * + * 3. type = PM8XXX_MPP_TYPE_D_BI_DIR - + * + * control specifies the pullup resistor value. It should be set to the + * value of one of PM8XXX_MPP_BI_PULLUP_*. + * + * 4. type = PM8XXX_MPP_TYPE_A_INPUT - + * + * control is unused; a value of 0 is sufficient. + * + * 5. type = PM8XXX_MPP_TYPE_A_OUTPUT - + * + * control specifies if analog output is enabled. It should be set to the + * value of one of PM8XXX_MPP_AOUT_CTRL_*. + * + * 6. type = PM8XXX_MPP_TYPE_SINK - + * + * control specifies if current sinking is enabled. It should be set to + * the value of one of PM8XXX_MPP_CS_CTRL_*. + * + * 7. type = PM8XXX_MPP_TYPE_DTEST_SINK - + * + * control specifies if current sinking is enabled. It should be set to + * the value of one of PM8XXX_MPP_DTEST_CS_CTRL_*. + * + * 8. type = PM8XXX_MPP_TYPE_DTEST_OUTPUT - + * + * control specifies which DTEST bus value to output. It should be set to + * the value of one of PM8XXX_MPP_DTEST_*. + */ +int pm8xxx_mpp_config(unsigned mpp, unsigned type, unsigned level, + unsigned control); + +#else + +static inline int pm8xxx_mpp_config(unsigned mpp, unsigned type, unsigned level, + unsigned control) +{ + return -ENXIO; +} + +#endif + +/* MPP Type: type */ +#define PM8XXX_MPP_TYPE_D_INPUT 0 +#define PM8XXX_MPP_TYPE_D_OUTPUT 1 +#define PM8XXX_MPP_TYPE_D_BI_DIR 2 +#define PM8XXX_MPP_TYPE_A_INPUT 3 +#define PM8XXX_MPP_TYPE_A_OUTPUT 4 +#define PM8XXX_MPP_TYPE_SINK 5 +#define PM8XXX_MPP_TYPE_DTEST_SINK 6 +#define PM8XXX_MPP_TYPE_DTEST_OUTPUT 7 + +/* Digital Input/Output: level */ +#define PM8XXX_MPP_DIG_LEVEL_VIO_0 0 +#define PM8XXX_MPP_DIG_LEVEL_VIO_1 1 +#define PM8XXX_MPP_DIG_LEVEL_VIO_2 2 +#define PM8XXX_MPP_DIG_LEVEL_VIO_3 3 +#define PM8XXX_MPP_DIG_LEVEL_VIO_4 4 +#define PM8XXX_MPP_DIG_LEVEL_VIO_5 5 +#define PM8XXX_MPP_DIG_LEVEL_VIO_6 6 +#define PM8XXX_MPP_DIG_LEVEL_VIO_7 7 + +/* Digital Input/Output: level [PM8058] */ +#define PM8058_MPP_DIG_LEVEL_VPH 0 +#define PM8058_MPP_DIG_LEVEL_S3 1 +#define PM8058_MPP_DIG_LEVEL_L2 2 +#define PM8058_MPP_DIG_LEVEL_L3 3 + +/* Digital Input/Output: level [PM8901] */ +#define PM8901_MPP_DIG_LEVEL_MSMIO 0 +#define PM8901_MPP_DIG_LEVEL_DIG 1 +#define PM8901_MPP_DIG_LEVEL_L5 2 +#define PM8901_MPP_DIG_LEVEL_S4 3 +#define PM8901_MPP_DIG_LEVEL_VPH 4 + +/* Digital Input/Output: level [PM8921] */ +#define PM8921_MPP_DIG_LEVEL_S4 1 +#define PM8921_MPP_DIG_LEVEL_L15 3 +#define PM8921_MPP_DIG_LEVEL_L17 4 +#define PM8921_MPP_DIG_LEVEL_VPH 7 + +/* Digital Input: control */ +#define PM8XXX_MPP_DIN_TO_INT 0 +#define PM8XXX_MPP_DIN_TO_DBUS1 1 +#define PM8XXX_MPP_DIN_TO_DBUS2 2 +#define PM8XXX_MPP_DIN_TO_DBUS3 3 + +/* Digital Output: control */ +#define PM8XXX_MPP_DOUT_CTRL_LOW 0 +#define PM8XXX_MPP_DOUT_CTRL_HIGH 1 +#define PM8XXX_MPP_DOUT_CTRL_MPP 2 +#define PM8XXX_MPP_DOUT_CTRL_INV_MPP 3 + +/* Bidirectional: control */ +#define PM8XXX_MPP_BI_PULLUP_1KOHM 0 +#define PM8XXX_MPP_BI_PULLUP_OPEN 1 +#define PM8XXX_MPP_BI_PULLUP_10KOHM 2 +#define PM8XXX_MPP_BI_PULLUP_30KOHM 3 + +/* Analog Input: level */ +#define PM8XXX_MPP_AIN_AMUX_CH5 0 +#define PM8XXX_MPP_AIN_AMUX_CH6 1 +#define PM8XXX_MPP_AIN_AMUX_CH7 2 +#define PM8XXX_MPP_AIN_AMUX_CH8 3 +#define PM8XXX_MPP_AIN_AMUX_CH9 4 +#define PM8XXX_MPP_AIN_AMUX_ABUS1 5 +#define PM8XXX_MPP_AIN_AMUX_ABUS2 6 +#define PM8XXX_MPP_AIN_AMUX_ABUS3 7 + +/* Analog Output: level */ +#define PM8XXX_MPP_AOUT_LVL_1V25 0 +#define PM8XXX_MPP_AOUT_LVL_1V25_2 1 +#define PM8XXX_MPP_AOUT_LVL_0V625 2 +#define PM8XXX_MPP_AOUT_LVL_0V3125 3 +#define PM8XXX_MPP_AOUT_LVL_MPP 4 +#define PM8XXX_MPP_AOUT_LVL_ABUS1 5 +#define PM8XXX_MPP_AOUT_LVL_ABUS2 6 +#define PM8XXX_MPP_AOUT_LVL_ABUS3 7 + +/* Analog Output: control */ +#define PM8XXX_MPP_AOUT_CTRL_DISABLE 0 +#define PM8XXX_MPP_AOUT_CTRL_ENABLE 1 +#define PM8XXX_MPP_AOUT_CTRL_MPP_HIGH_EN 2 +#define PM8XXX_MPP_AOUT_CTRL_MPP_LOW_EN 3 + +/* Current Sink: level */ +#define PM8XXX_MPP_CS_OUT_5MA 0 +#define PM8XXX_MPP_CS_OUT_10MA 1 +#define PM8XXX_MPP_CS_OUT_15MA 2 +#define PM8XXX_MPP_CS_OUT_20MA 3 +#define PM8XXX_MPP_CS_OUT_25MA 4 +#define PM8XXX_MPP_CS_OUT_30MA 5 +#define PM8XXX_MPP_CS_OUT_35MA 6 +#define PM8XXX_MPP_CS_OUT_40MA 7 + +/* Current Sink: control */ +#define PM8XXX_MPP_CS_CTRL_DISABLE 0 +#define PM8XXX_MPP_CS_CTRL_ENABLE 1 +#define PM8XXX_MPP_CS_CTRL_MPP_HIGH_EN 2 +#define PM8XXX_MPP_CS_CTRL_MPP_LOW_EN 3 + +/* DTEST Current Sink: control */ +#define PM8XXX_MPP_DTEST_CS_CTRL_EN1 0 +#define PM8XXX_MPP_DTEST_CS_CTRL_EN2 1 +#define PM8XXX_MPP_DTEST_CS_CTRL_EN3 2 +#define PM8XXX_MPP_DTEST_CS_CTRL_EN4 3 + +/* DTEST Digital Output: control */ +#define PM8XXX_MPP_DTEST_DBUS1 0 +#define PM8XXX_MPP_DTEST_DBUS2 1 +#define PM8XXX_MPP_DTEST_DBUS3 2 +#define PM8XXX_MPP_DTEST_DBUS4 3 + +#endif -- 1.7.1 Sent by an employee of the Qualcomm Innovation Center, Inc. The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/