From patchwork Mon Feb 4 15:40:42 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Haojian Zhuang X-Patchwork-Id: 14538 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 655C123F8B for ; Mon, 4 Feb 2013 15:42:06 +0000 (UTC) Received: from mail-vc0-f171.google.com (mail-vc0-f171.google.com [209.85.220.171]) by fiordland.canonical.com (Postfix) with ESMTP id EE276A18088 for ; Mon, 4 Feb 2013 15:42:05 +0000 (UTC) Received: by mail-vc0-f171.google.com with SMTP id p1so3938789vcq.16 for ; Mon, 04 Feb 2013 07:42:05 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:x-forwarded-to:x-forwarded-for:delivered-to:x-received :received-spf:x-received:from:to:cc:subject:date:message-id:x-mailer :x-gm-message-state; bh=fM7NrEFFNjbzhPuzprZsDU+4JEac38GfJ1C7IAyYfgg=; b=Zs1clg1roclW4rTEqXKzBSnP2QcvvBYYiry1QQWk2yKqGdKQDCQ0tIGcFYcUkH9E8/ B3MGOBOQck1/kaJGh0hN9czarjftEw6YQSFD1Cbkc8kA0ORkwc/fWDs4OswJNPgGlvdA IvJme3r8kcI3PEqlUAMQzh+DFNR/7ruNSbFKBLBXUqoO+21eHQwO6L3O46tHrZYx3oM2 C2azTPKYenF4vVdJYRSn7nxNGf6KK2fnQeH/lu5RM9RFXwoMhjtRFtqNP5cQOvifUZr6 C6sidRuNdpqbeNMXjV8ezEnkQakLlB1ulexBvauX/f9t7QDC4+M7hPdzrzqmgvenGdlA FyGQ== X-Received: by 10.220.219.204 with SMTP id hv12mr22335471vcb.71.1359992525207; Mon, 04 Feb 2013 07:42:05 -0800 (PST) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.58.252.8 with SMTP id zo8csp92937vec; Mon, 4 Feb 2013 07:42:04 -0800 (PST) X-Received: by 10.50.7.231 with SMTP id m7mr7297092iga.0.1359992524072; Mon, 04 Feb 2013 07:42:04 -0800 (PST) Received: from mail-pa0-f53.google.com (mail-pa0-f53.google.com [209.85.220.53]) by mx.google.com with ESMTPS id p7si17984796pav.50.2013.02.04.07.42.03 (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 04 Feb 2013 07:42:03 -0800 (PST) Received-SPF: neutral (google.com: 209.85.220.53 is neither permitted nor denied by best guess record for domain of haojian.zhuang@linaro.org) client-ip=209.85.220.53; Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.220.53 is neither permitted nor denied by best guess record for domain of haojian.zhuang@linaro.org) smtp.mail=haojian.zhuang@linaro.org Received: by mail-pa0-f53.google.com with SMTP id bg4so3379130pad.26 for ; Mon, 04 Feb 2013 07:42:03 -0800 (PST) X-Received: by 10.66.83.8 with SMTP id m8mr31921832pay.40.1359992523360; Mon, 04 Feb 2013 07:42:03 -0800 (PST) Received: from localhost.localdomain ([67.198.145.34]) by mx.google.com with ESMTPS id d1sm22254330pav.6.2013.02.04.07.41.57 (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 04 Feb 2013 07:42:02 -0800 (PST) From: Haojian Zhuang To: sameo@linux.intel.com, qingx@marvell.com, grant.likely@secretlab.ca, rob.herring@calxeda.com, cxie4@marvell.com, linux-kernel@vger.kernel.org, devicetree-discuss@lists.ozlabs.org Cc: patches@linaro.org, Haojian Zhuang Subject: [PATCH 1/6] mfd: max8925: add irqdomain for dt Date: Mon, 4 Feb 2013 23:40:42 +0800 Message-Id: <1359992448-22229-1-git-send-email-haojian.zhuang@linaro.org> X-Mailer: git-send-email 1.7.10.4 X-Gm-Message-State: ALoCoQmZ1xUu3ZpotNUPCDxLGqQHETc4MANCDtNn4hNgTE6/QVoooElXhxQgdYSWhdj6RGuSbNcs From: Qing Xu 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 Signed-off-by: Haojian Zhuang --- drivers/mfd/max8925-core.c | 73 +++++++++++++++++++++++++------------------ drivers/mfd/max8925-i2c.c | 36 +++++++++++++++++++-- include/linux/mfd/max8925.h | 3 +- 3 files changed, 78 insertions(+), 34 deletions(-) diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c index e32466e..0ad8d9a 100644 --- a/drivers/mfd/max8925-core.c +++ b/drivers/mfd/max8925-core.c @@ -14,10 +14,13 @@ #include #include #include +#include #include #include #include #include +#include +#include static struct resource bk_resources[] = { { 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,30 @@ 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 | IRQF_ONESHOT, "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 +718,6 @@ tsc_irq: return 0; } chip->tsc_irq = pdata->tsc_irq; - ret = request_threaded_irq(chip->tsc_irq, NULL, max8925_tsc_irq, flags | IRQF_ONESHOT, "max8925-tsc", chip); if (ret) { @@ -875,11 +888,11 @@ int 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), + ARRAY_SIZE(power_devs), &power_supply_resources[0], 0, NULL); if (ret < 0) { - dev_err(chip->dev, "Failed to add power supply " - "subdev\n"); + dev_err(chip->dev, + "Failed to add power supply subdev\n"); goto out_dev; } } diff --git a/drivers/mfd/max8925-i2c.c b/drivers/mfd/max8925-i2c.c index 00b5b45..92bbebd 100644 --- a/drivers/mfd/max8925-i2c.c +++ b/drivers/mfd/max8925-i2c.c @@ -135,13 +135,37 @@ static const struct i2c_device_id max8925_id_table[] = { }; MODULE_DEVICE_TABLE(i2c, max8925_id_table); +static int max8925_dt_init(struct device_node *np, struct device *dev, + struct max8925_platform_data *pdata) +{ + int ret; + + ret = of_property_read_u32(np, "maxim,tsc-irq", &pdata->tsc_irq); + if (ret) { + dev_err(dev, "Not found maxim,tsc-irq property\n"); + return -EINVAL; + } + return 0; +} + static int 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 +227,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 = max8925_remove, @@ -217,7 +248,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; };