Skip to content

Commit

Permalink
mfd: max8925: Add irqdomain for dt
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Qing Xu authored and Samuel Ortiz committed Feb 13, 2013
1 parent dcd560c commit 4e405ae
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 34 deletions.
73 changes: 43 additions & 30 deletions drivers/mfd/max8925-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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[] = {
{ 0x84, 0x84, "mode control", IORESOURCE_REG, },
Expand Down Expand Up @@ -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);
Expand All @@ -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);

Expand All @@ -704,7 +718,6 @@ static int max8925_irq_init(struct max8925_chip *chip, int 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) {
Expand Down Expand Up @@ -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;
}
}
Expand Down
36 changes: 33 additions & 3 deletions drivers/mfd/max8925-i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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,
Expand All @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion include/linux/mfd/max8925.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ enum {
MAX8925_NR_IRQS,
};



struct max8925_chip {
struct device *dev;
struct i2c_client *i2c;
Expand All @@ -201,7 +203,6 @@ struct max8925_chip {
int irq_base;
int core_irq;
int tsc_irq;

unsigned int wakeup_flag;
};

Expand Down

0 comments on commit 4e405ae

Please sign in to comment.