[PATCH v3 1/7] mfd: max8925: add irqdomain for dt

Haojian Zhuang haojian.zhuang at gmail.com
Tue Dec 4 18:08:44 EST 2012


On Thu, Nov 29, 2012 at 11:29 AM, Qing Xu <qingx at marvell.com> wrote:
> From: Qing Xu <qingx at marvell.com>
>
> Add irqdomains for max8925's main irq, wrap irq register operations
> into irqdomain's map func. it is necessary for dt support.
>
> Also, add dt support for max8925 driver.
>
> Signed-off-by: Qing Xu <qingx at marvell.com>
> ---
>  drivers/mfd/max8925-core.c  |   69 ++++++++++++++++++++++++++-----------------
>  drivers/mfd/max8925-i2c.c   |   37 +++++++++++++++++++++--
>  include/linux/mfd/max8925.h |    3 +-
>  3 files changed, 78 insertions(+), 31 deletions(-)
>
> diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c
> index 1e0ab0a..d0ebdbf 100644
> --- a/drivers/mfd/max8925-core.c
> +++ b/drivers/mfd/max8925-core.c
> @@ -14,10 +14,13 @@
>  #include <linux/i2c.h>
>  #include <linux/irq.h>
>  #include <linux/interrupt.h>
> +#include <linux/irqdomain.h>
>  #include <linux/platform_device.h>
>  #include <linux/regulator/machine.h>
>  #include <linux/mfd/core.h>
>  #include <linux/mfd/max8925.h>
> +#include <linux/of.h>
> +#include <linux/of_platform.h>
>
>  static struct resource bk_resources[] __devinitdata = {
>         { 0x84, 0x84, "mode control", IORESOURCE_REG, },
> @@ -639,17 +642,33 @@ static struct irq_chip max8925_irq_chip = {
>         .irq_disable    = max8925_irq_disable,
>  };
>
> +static int max8925_irq_domain_map(struct irq_domain *d, unsigned int virq,
> +                                irq_hw_number_t hw)
> +{
> +       irq_set_chip_data(virq, d->host_data);
> +       irq_set_chip_and_handler(virq, &max8925_irq_chip, handle_edge_irq);
> +       irq_set_nested_thread(virq, 1);
> +#ifdef CONFIG_ARM
> +       set_irq_flags(virq, IRQF_VALID);
> +#else
> +       irq_set_noprobe(virq);
> +#endif
> +       return 0;
> +}
> +
> +static struct irq_domain_ops max8925_irq_domain_ops = {
> +       .map    = max8925_irq_domain_map,
> +       .xlate  = irq_domain_xlate_onetwocell,
> +};
> +
> +
>  static int max8925_irq_init(struct max8925_chip *chip, int irq,
>                             struct max8925_platform_data *pdata)
>  {
>         unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
> -       int i, ret;
> -       int __irq;
> +       int ret;
> +       struct device_node *node = chip->dev->of_node;
>
> -       if (!pdata || !pdata->irq_base) {
> -               dev_warn(chip->dev, "No interrupt support on IRQ base\n");
> -               return -EINVAL;
> -       }
>         /* clear all interrupts */
>         max8925_reg_read(chip->i2c, MAX8925_CHG_IRQ1);
>         max8925_reg_read(chip->i2c, MAX8925_CHG_IRQ2);
> @@ -667,35 +686,32 @@ static int max8925_irq_init(struct max8925_chip *chip, int irq,
>         max8925_reg_write(chip->rtc, MAX8925_RTC_IRQ_MASK, 0xff);
>
>         mutex_init(&chip->irq_lock);
> -       chip->core_irq = irq;
> -       chip->irq_base = pdata->irq_base;
>
> -       /* register with genirq */
> -       for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) {
> -               __irq = i + chip->irq_base;
> -               irq_set_chip_data(__irq, chip);
> -               irq_set_chip_and_handler(__irq, &max8925_irq_chip,
> -                                        handle_edge_irq);
> -               irq_set_nested_thread(__irq, 1);
> -#ifdef CONFIG_ARM
> -               set_irq_flags(__irq, IRQF_VALID);
> -#else
> -               irq_set_noprobe(__irq);
> -#endif
> -       }
> -       if (!irq) {
> -               dev_warn(chip->dev, "No interrupt support on core IRQ\n");
> -               goto tsc_irq;
> +       chip->irq_base = irq_alloc_descs(-1, 0, MAX8925_NR_IRQS, 0);
> +       if (chip->irq_base < 0) {
> +               dev_err(chip->dev, "Failed to allocate interrupts, ret:%d\n",
> +                       chip->irq_base);
> +               return -EBUSY;
>         }
>
> +       irq_domain_add_legacy(node, MAX8925_NR_IRQS, chip->irq_base, 0,
> +                             &max8925_irq_domain_ops, chip);
> +
> +       /* request irq handler for pmic main irq*/
> +
> +       chip->core_irq = irq;
> +       if (!chip->core_irq)
> +               return -EBUSY;
>         ret = request_threaded_irq(irq, NULL, max8925_irq, flags,
>                                    "max8925", chip);
>         if (ret) {
>                 dev_err(chip->dev, "Failed to request core IRQ: %d\n", ret);
>                 chip->core_irq = 0;
> +               return -EBUSY;
>         }
>
> -tsc_irq:
> +       /* request irq handler for pmic tsc irq*/
> +
>         /* mask TSC interrupt */
>         max8925_reg_write(chip->adc, MAX8925_TSC_IRQ_MASK, 0x0f);
>
> @@ -704,7 +720,6 @@ tsc_irq:
>                 return 0;
>         }
>         chip->tsc_irq = pdata->tsc_irq;
> -
>         ret = request_threaded_irq(chip->tsc_irq, NULL, max8925_tsc_irq,
>                                    flags, "max8925-tsc", chip);
>         if (ret) {
> @@ -876,7 +891,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip,
>         if (pdata && pdata->power) {
>                 ret = mfd_add_devices(chip->dev, 0, &power_devs[0],
>                                         ARRAY_SIZE(power_devs),
> -                                     &power_supply_resources[0], 0, NULL);
> +                                       &power_supply_resources[0], 0, NULL);
>                 if (ret < 0) {
>                         dev_err(chip->dev, "Failed to add power supply "
>                                 "subdev\n");
> diff --git a/drivers/mfd/max8925-i2c.c b/drivers/mfd/max8925-i2c.c
> index d9e4b36..46df784 100644
> --- a/drivers/mfd/max8925-i2c.c
> +++ b/drivers/mfd/max8925-i2c.c
> @@ -135,13 +135,38 @@ static const struct i2c_device_id max8925_id_table[] = {
>  };
>  MODULE_DEVICE_TABLE(i2c, max8925_id_table);
>
> +static int __devinit max8925_dt_init(struct device_node *np,
> +                                   struct device *dev,
> +                                   struct max8925_platform_data *pdata)
> +{
> +       int ret;
> +
> +       ret = of_property_read_u32(np, "tsc-irq", &pdata->tsc_irq);
> +       if (ret) {
> +               dev_err(dev, "Not found \"tsc-irq\" property\n");
> +               return -EINVAL;
> +       }
> +       return 0;
> +}
> +
>  static int __devinit max8925_probe(struct i2c_client *client,
>                                    const struct i2c_device_id *id)
>  {
>         struct max8925_platform_data *pdata = client->dev.platform_data;
>         static struct max8925_chip *chip;
> -
> -       if (!pdata) {
> +       struct device_node *node = client->dev.of_node;
> +
> +       if (node && !pdata) {
> +               /* parse DT to get platform data */
> +               pdata = devm_kzalloc(&client->dev,
> +                                    sizeof(struct max8925_platform_data),
> +                                    GFP_KERNEL);
> +               if (!pdata)
> +                       return -ENOMEM;
> +
> +               if (max8925_dt_init(node, &client->dev, pdata))
> +                       return -EINVAL;
> +       } else if (!pdata) {
>                 pr_info("%s: platform data is missing\n", __func__);
>                 return -EINVAL;
>         }
> @@ -203,11 +228,18 @@ static int max8925_resume(struct device *dev)
>
>  static SIMPLE_DEV_PM_OPS(max8925_pm_ops, max8925_suspend, max8925_resume);
>
> +static const struct of_device_id max8925_dt_ids[] = {
> +       { .compatible = "maxim,max8925", },
> +       {},
> +};
> +MODULE_DEVICE_TABLE(of, max8925_dt_ids);
> +
>  static struct i2c_driver max8925_driver = {
>         .driver = {
>                 .name   = "max8925",
>                 .owner  = THIS_MODULE,
>                 .pm     = &max8925_pm_ops,
> +               .of_match_table = of_match_ptr(max8925_dt_ids),
>         },
>         .probe          = max8925_probe,
>         .remove         = __devexit_p(max8925_remove),
> @@ -217,7 +249,6 @@ static struct i2c_driver max8925_driver = {
>  static int __init max8925_i2c_init(void)
>  {
>         int ret;
> -
>         ret = i2c_add_driver(&max8925_driver);
>         if (ret != 0)
>                 pr_err("Failed to register MAX8925 I2C driver: %d\n", ret);
> diff --git a/include/linux/mfd/max8925.h b/include/linux/mfd/max8925.h
> index 74d8e29..ce8502e 100644
> --- a/include/linux/mfd/max8925.h
> +++ b/include/linux/mfd/max8925.h
> @@ -190,6 +190,8 @@ enum {
>         MAX8925_NR_IRQS,
>  };
>
> +
> +
>  struct max8925_chip {
>         struct device           *dev;
>         struct i2c_client       *i2c;
> @@ -201,7 +203,6 @@ struct max8925_chip {
>         int                     irq_base;
>         int                     core_irq;
>         int                     tsc_irq;
> -
>         unsigned int            wakeup_flag;
>  };
>
> --
> 1.7.0.4
>

Acked-by: Haojian Zhuang <haojian.zhuang at gmail.com>


More information about the devicetree-discuss mailing list