lkml.org 
[lkml]   [2011]   [Mar]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[Qualcomm PM8921 MFD v2 4/6] mfd: pm8xxx-mpp: Add pm8xxx MPP driver
    Date
    From: David Collins <collinsd@codeaurora.org>

    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 <collinsd@codeaurora.org>
    ---
    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 <linux/platform_device.h>
    +#include <linux/gpio.h>
    +#include <linux/seq_file.h>
    +#include <linux/slab.h>
    +#include <linux/mfd/pm8xxx/core.h>
    +#include <linux/mfd/pm8xxx/mpp.h>
    +
    +/* 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 <linux/device.h>
    #include <linux/mfd/pm8xxx/irq.h>
    #include <linux/mfd/pm8xxx/gpio.h>
    +#include <linux/mfd/pm8xxx/mpp.h>

    #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 <linux/errno.h>
    +
    +#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.


    \
     
     \ /
      Last update: 2011-03-08 07:15    [W:0.057 / U:1.044 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site