Hi, On Sun, 2014-02-02 at 02:23 +0400, Vladimir Barinov wrote: > Index: battery-2.6/drivers/power/modelgauge_battery.c > =================================================================== > --- /dev/null 1970-01-01 00:00:00.000000000 +0000 > +++ battery-2.6/drivers/power/modelgauge_battery.c 2014-02-02 01:29:34.314614874 +0400 > @@ -0,0 +1,838 @@ > +/* > + * Maxim ModelGauge ICs fuel gauge driver > + * > + * Author: Vladimir Barinov <source@xxxxxxxxxxxxxxxxxx> > + * Copyright (C) 2013 Cogent Embedded, Inc. > + * > + * This program is free software; you can redistribute it and/or modify it > + * under the terms of the GNU General Public License as published by the > + * Free Software Foundation; either version 2 of the License, or (at your > + * option) any later version. > + */ (...) > +static int modelgauge_probe(struct i2c_client *client, > + const struct i2c_device_id *id) > +{ > + struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); > + struct modelgauge_priv *priv; > + int ret; > + > + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) > + return -EIO; > + > + priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); > + if (!priv) > + return -ENOMEM; > + > + if (client->dev.of_node) > + priv->pdata = modelgauge_parse_dt(&client->dev); > + else > + priv->pdata = client->dev.platform_data; > + > + priv->dev = &client->dev; > + priv->chip = id->driver_data; > + > + i2c_set_clientdata(client, priv); > + > + priv->regmap = devm_regmap_init_i2c(client, &modelgauge_regmap); > + if (IS_ERR(priv->regmap)) > + return PTR_ERR(priv->regmap); > + > + priv->battery.name = "modelgauge_battery"; > + priv->battery.type = POWER_SUPPLY_TYPE_BATTERY; > + priv->battery.get_property = modelgauge_get_property; > + priv->battery.properties = modelgauge_battery_props; > + priv->battery.num_properties = ARRAY_SIZE(modelgauge_battery_props); > + > + INIT_WORK(&priv->load_work, modelgauge_load_model_work); > + INIT_DELAYED_WORK(&priv->rcomp_work, modelgauge_update_rcomp_work); > + > + ret = modelgauge_init(priv); > + if (ret) > + return ret; > + > + ret = power_supply_register(&client->dev, &priv->battery); > + if (ret) { > + dev_err(priv->dev, "failed: power supply register\n"); > + goto err_supply; > + } > + > + if (client->irq) { > + switch (priv->chip) { > + case ID_MAX17040: > + case ID_MAX17041: > + dev_err(priv->dev, "alert line is not supported\n"); > + ret = -EINVAL; > + goto err_irq; > + default: > + ret = devm_request_threaded_irq(priv->dev, client->irq, > + NULL, > + modelgauge_irq_handler, > + IRQF_TRIGGER_FALLING, > + priv->battery.name, > + priv); Shouldn't it be also IRQF_ONESHOT? Without this you may get an error: genirq: Threaded irq requested with handler=NULL and !ONESHOT for irq > + if (ret) { > + dev_err(priv->dev, "failed to request irq %d\n", > + client->irq); > + goto err_irq; > + } > + } > + } > + > + return 0; > + > +err_irq: > + power_supply_unregister(&priv->battery); > +err_supply: > + cancel_work_sync(&priv->load_work); > + cancel_delayed_work_sync(&priv->rcomp_work); > + return ret; > +} > + > +static int modelgauge_remove(struct i2c_client *client) > +{ > + struct modelgauge_priv *priv = i2c_get_clientdata(client); > + > + cancel_work_sync(&priv->load_work); > + cancel_delayed_work_sync(&priv->rcomp_work); > + > + power_supply_unregister(&priv->battery); > + return 0; > +} > + > +#ifdef CONFIG_PM_SLEEP > +static int modelgauge_suspend(struct device *dev) > +{ > + struct i2c_client *client = to_i2c_client(dev); > + struct modelgauge_priv *priv = i2c_get_clientdata(client); > + struct modelgauge_platform_data *pdata = priv->pdata; > + > + if (pdata && pdata->get_temperature) > + cancel_delayed_work_sync(&priv->rcomp_work); > + > + switch (priv->chip) { > + case ID_MAX17040: > + case ID_MAX17041: > + return 0; > + default: > + if (client->irq) { > + disable_irq(client->irq); > + enable_irq_wake(client->irq); > + } > + } > + > + return 0; > +} > + > +static int modelgauge_resume(struct device *dev) > +{ > + struct i2c_client *client = to_i2c_client(dev); > + struct modelgauge_priv *priv = i2c_get_clientdata(client); > + struct modelgauge_platform_data *pdata = priv->pdata; > + > + if (pdata && pdata->get_temperature) > + schedule_delayed_work(&priv->rcomp_work, > + msecs_to_jiffies(MODELGAUGE_RCOMP_UPDATE_DELAY)); > + > + switch (priv->chip) { > + case ID_MAX17040: > + case ID_MAX17041: > + return 0; > + default: > + if (client->irq) { > + disable_irq_wake(client->irq); > + enable_irq(client->irq); > + } > + } > + > + return 0; > +} > + > +static SIMPLE_DEV_PM_OPS(modelgauge_pm_ops, > + modelgauge_suspend, modelgauge_resume); > +#define MODELGAUGE_PM_OPS (&modelgauge_pm_ops) > +#else > +#define MODELGAUGE_PM_OPS NULL > +#endif /* CONFIG_PM_SLEEP */ You can simplify this into: +} +#endif /* CONFIG_PM_SLEEP */ + +static SIMPLE_DEV_PM_OPS(modelgauge_pm_ops, + modelgauge_suspend, modelgauge_resume); And later: +static struct i2c_driver modelgauge_i2c_driver = { + .driver = { + .name = DRV_NAME, + .of_match_table = of_match_ptr(modelgauge_match), + .pm = &modelgauge_pm_ops, Anyway, I like the idea of merging these drivers so I'm happy to test it further. Best regards, Krzysztof -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html