aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd
diff options
context:
space:
mode:
authorQing Xu <qingx@marvell.com>2013-02-04 10:40:42 -0500
committerSamuel Ortiz <sameo@linux.intel.com>2013-02-13 18:23:00 -0500
commit4e405ae256b7e04f7c1213136f3bfd9fb76e2023 (patch)
treef821f9b999202d623c50eafcb9db5431937f1f46 /drivers/mfd
parentdcd560c8587171bb22c75c41ac2a70986bbbde7f (diff)
mfd: max8925: Add irqdomain for dt
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@marvell.com> Signed-off-by: Haojian Zhuang <haojian.zhuang@gmail.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/max8925-core.c73
-rw-r--r--drivers/mfd/max8925-i2c.c36
2 files changed, 76 insertions, 33 deletions
diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c
index e32466e865b9..0ad8d9a7c15a 100644
--- a/drivers/mfd/max8925-core.c
+++ b/drivers/mfd/max8925-core.c
@@ -14,10 +14,13 @@
14#include <linux/i2c.h> 14#include <linux/i2c.h>
15#include <linux/irq.h> 15#include <linux/irq.h>
16#include <linux/interrupt.h> 16#include <linux/interrupt.h>
17#include <linux/irqdomain.h>
17#include <linux/platform_device.h> 18#include <linux/platform_device.h>
18#include <linux/regulator/machine.h> 19#include <linux/regulator/machine.h>
19#include <linux/mfd/core.h> 20#include <linux/mfd/core.h>
20#include <linux/mfd/max8925.h> 21#include <linux/mfd/max8925.h>
22#include <linux/of.h>
23#include <linux/of_platform.h>
21 24
22static struct resource bk_resources[] = { 25static struct resource bk_resources[] = {
23 { 0x84, 0x84, "mode control", IORESOURCE_REG, }, 26 { 0x84, 0x84, "mode control", IORESOURCE_REG, },
@@ -639,17 +642,33 @@ static struct irq_chip max8925_irq_chip = {
639 .irq_disable = max8925_irq_disable, 642 .irq_disable = max8925_irq_disable,
640}; 643};
641 644
645static int max8925_irq_domain_map(struct irq_domain *d, unsigned int virq,
646 irq_hw_number_t hw)
647{
648 irq_set_chip_data(virq, d->host_data);
649 irq_set_chip_and_handler(virq, &max8925_irq_chip, handle_edge_irq);
650 irq_set_nested_thread(virq, 1);
651#ifdef CONFIG_ARM
652 set_irq_flags(virq, IRQF_VALID);
653#else
654 irq_set_noprobe(virq);
655#endif
656 return 0;
657}
658
659static struct irq_domain_ops max8925_irq_domain_ops = {
660 .map = max8925_irq_domain_map,
661 .xlate = irq_domain_xlate_onetwocell,
662};
663
664
642static int max8925_irq_init(struct max8925_chip *chip, int irq, 665static int max8925_irq_init(struct max8925_chip *chip, int irq,
643 struct max8925_platform_data *pdata) 666 struct max8925_platform_data *pdata)
644{ 667{
645 unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; 668 unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
646 int i, ret; 669 int ret;
647 int __irq; 670 struct device_node *node = chip->dev->of_node;
648 671
649 if (!pdata || !pdata->irq_base) {
650 dev_warn(chip->dev, "No interrupt support on IRQ base\n");
651 return -EINVAL;
652 }
653 /* clear all interrupts */ 672 /* clear all interrupts */
654 max8925_reg_read(chip->i2c, MAX8925_CHG_IRQ1); 673 max8925_reg_read(chip->i2c, MAX8925_CHG_IRQ1);
655 max8925_reg_read(chip->i2c, MAX8925_CHG_IRQ2); 674 max8925_reg_read(chip->i2c, MAX8925_CHG_IRQ2);
@@ -667,35 +686,30 @@ static int max8925_irq_init(struct max8925_chip *chip, int irq,
667 max8925_reg_write(chip->rtc, MAX8925_RTC_IRQ_MASK, 0xff); 686 max8925_reg_write(chip->rtc, MAX8925_RTC_IRQ_MASK, 0xff);
668 687
669 mutex_init(&chip->irq_lock); 688 mutex_init(&chip->irq_lock);
670 chip->core_irq = irq; 689 chip->irq_base = irq_alloc_descs(-1, 0, MAX8925_NR_IRQS, 0);
671 chip->irq_base = pdata->irq_base; 690 if (chip->irq_base < 0) {
672 691 dev_err(chip->dev, "Failed to allocate interrupts, ret:%d\n",
673 /* register with genirq */ 692 chip->irq_base);
674 for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) { 693 return -EBUSY;
675 __irq = i + chip->irq_base;
676 irq_set_chip_data(__irq, chip);
677 irq_set_chip_and_handler(__irq, &max8925_irq_chip,
678 handle_edge_irq);
679 irq_set_nested_thread(__irq, 1);
680#ifdef CONFIG_ARM
681 set_irq_flags(__irq, IRQF_VALID);
682#else
683 irq_set_noprobe(__irq);
684#endif
685 }
686 if (!irq) {
687 dev_warn(chip->dev, "No interrupt support on core IRQ\n");
688 goto tsc_irq;
689 } 694 }
690 695
696 irq_domain_add_legacy(node, MAX8925_NR_IRQS, chip->irq_base, 0,
697 &max8925_irq_domain_ops, chip);
698
699 /* request irq handler for pmic main irq*/
700 chip->core_irq = irq;
701 if (!chip->core_irq)
702 return -EBUSY;
691 ret = request_threaded_irq(irq, NULL, max8925_irq, flags | IRQF_ONESHOT, 703 ret = request_threaded_irq(irq, NULL, max8925_irq, flags | IRQF_ONESHOT,
692 "max8925", chip); 704 "max8925", chip);
693 if (ret) { 705 if (ret) {
694 dev_err(chip->dev, "Failed to request core IRQ: %d\n", ret); 706 dev_err(chip->dev, "Failed to request core IRQ: %d\n", ret);
695 chip->core_irq = 0; 707 chip->core_irq = 0;
708 return -EBUSY;
696 } 709 }
697 710
698tsc_irq: 711 /* request irq handler for pmic tsc irq*/
712
699 /* mask TSC interrupt */ 713 /* mask TSC interrupt */
700 max8925_reg_write(chip->adc, MAX8925_TSC_IRQ_MASK, 0x0f); 714 max8925_reg_write(chip->adc, MAX8925_TSC_IRQ_MASK, 0x0f);
701 715
@@ -704,7 +718,6 @@ tsc_irq:
704 return 0; 718 return 0;
705 } 719 }
706 chip->tsc_irq = pdata->tsc_irq; 720 chip->tsc_irq = pdata->tsc_irq;
707
708 ret = request_threaded_irq(chip->tsc_irq, NULL, max8925_tsc_irq, 721 ret = request_threaded_irq(chip->tsc_irq, NULL, max8925_tsc_irq,
709 flags | IRQF_ONESHOT, "max8925-tsc", chip); 722 flags | IRQF_ONESHOT, "max8925-tsc", chip);
710 if (ret) { 723 if (ret) {
@@ -875,11 +888,11 @@ int max8925_device_init(struct max8925_chip *chip,
875 888
876 if (pdata && pdata->power) { 889 if (pdata && pdata->power) {
877 ret = mfd_add_devices(chip->dev, 0, &power_devs[0], 890 ret = mfd_add_devices(chip->dev, 0, &power_devs[0],
878 ARRAY_SIZE(power_devs), 891 ARRAY_SIZE(power_devs),
879 &power_supply_resources[0], 0, NULL); 892 &power_supply_resources[0], 0, NULL);
880 if (ret < 0) { 893 if (ret < 0) {
881 dev_err(chip->dev, "Failed to add power supply " 894 dev_err(chip->dev,
882 "subdev\n"); 895 "Failed to add power supply subdev\n");
883 goto out_dev; 896 goto out_dev;
884 } 897 }
885 } 898 }
diff --git a/drivers/mfd/max8925-i2c.c b/drivers/mfd/max8925-i2c.c
index 00b5b456063d..92bbebd31598 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[] = {
135}; 135};
136MODULE_DEVICE_TABLE(i2c, max8925_id_table); 136MODULE_DEVICE_TABLE(i2c, max8925_id_table);
137 137
138static int max8925_dt_init(struct device_node *np, struct device *dev,
139 struct max8925_platform_data *pdata)
140{
141 int ret;
142
143 ret = of_property_read_u32(np, "maxim,tsc-irq", &pdata->tsc_irq);
144 if (ret) {
145 dev_err(dev, "Not found maxim,tsc-irq property\n");
146 return -EINVAL;
147 }
148 return 0;
149}
150
138static int max8925_probe(struct i2c_client *client, 151static int max8925_probe(struct i2c_client *client,
139 const struct i2c_device_id *id) 152 const struct i2c_device_id *id)
140{ 153{
141 struct max8925_platform_data *pdata = client->dev.platform_data; 154 struct max8925_platform_data *pdata = client->dev.platform_data;
142 static struct max8925_chip *chip; 155 static struct max8925_chip *chip;
143 156 struct device_node *node = client->dev.of_node;
144 if (!pdata) { 157
158 if (node && !pdata) {
159 /* parse DT to get platform data */
160 pdata = devm_kzalloc(&client->dev,
161 sizeof(struct max8925_platform_data),
162 GFP_KERNEL);
163 if (!pdata)
164 return -ENOMEM;
165
166 if (max8925_dt_init(node, &client->dev, pdata))
167 return -EINVAL;
168 } else if (!pdata) {
145 pr_info("%s: platform data is missing\n", __func__); 169 pr_info("%s: platform data is missing\n", __func__);
146 return -EINVAL; 170 return -EINVAL;
147 } 171 }
@@ -203,11 +227,18 @@ static int max8925_resume(struct device *dev)
203 227
204static SIMPLE_DEV_PM_OPS(max8925_pm_ops, max8925_suspend, max8925_resume); 228static SIMPLE_DEV_PM_OPS(max8925_pm_ops, max8925_suspend, max8925_resume);
205 229
230static const struct of_device_id max8925_dt_ids[] = {
231 { .compatible = "maxim,max8925", },
232 {},
233};
234MODULE_DEVICE_TABLE(of, max8925_dt_ids);
235
206static struct i2c_driver max8925_driver = { 236static struct i2c_driver max8925_driver = {
207 .driver = { 237 .driver = {
208 .name = "max8925", 238 .name = "max8925",
209 .owner = THIS_MODULE, 239 .owner = THIS_MODULE,
210 .pm = &max8925_pm_ops, 240 .pm = &max8925_pm_ops,
241 .of_match_table = of_match_ptr(max8925_dt_ids),
211 }, 242 },
212 .probe = max8925_probe, 243 .probe = max8925_probe,
213 .remove = max8925_remove, 244 .remove = max8925_remove,
@@ -217,7 +248,6 @@ static struct i2c_driver max8925_driver = {
217static int __init max8925_i2c_init(void) 248static int __init max8925_i2c_init(void)
218{ 249{
219 int ret; 250 int ret;
220
221 ret = i2c_add_driver(&max8925_driver); 251 ret = i2c_add_driver(&max8925_driver);
222 if (ret != 0) 252 if (ret != 0)
223 pr_err("Failed to register MAX8925 I2C driver: %d\n", ret); 253 pr_err("Failed to register MAX8925 I2C driver: %d\n", ret);