184c99db879314d58e0064f02b481f668f45d0070Ashish Jangam/*
284c99db879314d58e0064f02b481f668f45d0070Ashish Jangam * I2C access for DA9052 PMICs.
384c99db879314d58e0064f02b481f668f45d0070Ashish Jangam *
484c99db879314d58e0064f02b481f668f45d0070Ashish Jangam * Copyright(c) 2011 Dialog Semiconductor Ltd.
584c99db879314d58e0064f02b481f668f45d0070Ashish Jangam *
684c99db879314d58e0064f02b481f668f45d0070Ashish Jangam * Author: David Dajun Chen <dchen@diasemi.com>
784c99db879314d58e0064f02b481f668f45d0070Ashish Jangam *
884c99db879314d58e0064f02b481f668f45d0070Ashish Jangam * This program is free software; you can redistribute it and/or modify
984c99db879314d58e0064f02b481f668f45d0070Ashish Jangam * it under the terms of the GNU General Public License as published by
1084c99db879314d58e0064f02b481f668f45d0070Ashish Jangam * the Free Software Foundation; either version 2 of the License, or
1184c99db879314d58e0064f02b481f668f45d0070Ashish Jangam * (at your option) any later version.
1284c99db879314d58e0064f02b481f668f45d0070Ashish Jangam *
1384c99db879314d58e0064f02b481f668f45d0070Ashish Jangam */
1484c99db879314d58e0064f02b481f668f45d0070Ashish Jangam
1584c99db879314d58e0064f02b481f668f45d0070Ashish Jangam#include <linux/device.h>
1684c99db879314d58e0064f02b481f668f45d0070Ashish Jangam#include <linux/module.h>
1784c99db879314d58e0064f02b481f668f45d0070Ashish Jangam#include <linux/input.h>
1884c99db879314d58e0064f02b481f668f45d0070Ashish Jangam#include <linux/mfd/core.h>
1984c99db879314d58e0064f02b481f668f45d0070Ashish Jangam#include <linux/i2c.h>
2084c99db879314d58e0064f02b481f668f45d0070Ashish Jangam#include <linux/err.h>
2184c99db879314d58e0064f02b481f668f45d0070Ashish Jangam
2284c99db879314d58e0064f02b481f668f45d0070Ashish Jangam#include <linux/mfd/da9052/da9052.h>
2384c99db879314d58e0064f02b481f668f45d0070Ashish Jangam#include <linux/mfd/da9052/reg.h>
2484c99db879314d58e0064f02b481f668f45d0070Ashish Jangam
2584c99db879314d58e0064f02b481f668f45d0070Ashish Jangamstatic int da9052_i2c_enable_multiwrite(struct da9052 *da9052)
2684c99db879314d58e0064f02b481f668f45d0070Ashish Jangam{
2784c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	int reg_val, ret;
2884c99db879314d58e0064f02b481f668f45d0070Ashish Jangam
2984c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	ret = regmap_read(da9052->regmap, DA9052_CONTROL_B_REG, &reg_val);
3084c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	if (ret < 0)
3184c99db879314d58e0064f02b481f668f45d0070Ashish Jangam		return ret;
3284c99db879314d58e0064f02b481f668f45d0070Ashish Jangam
3384c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	if (reg_val & DA9052_CONTROL_B_WRITEMODE) {
3484c99db879314d58e0064f02b481f668f45d0070Ashish Jangam		reg_val &= ~DA9052_CONTROL_B_WRITEMODE;
3584c99db879314d58e0064f02b481f668f45d0070Ashish Jangam		ret = regmap_write(da9052->regmap, DA9052_CONTROL_B_REG,
3684c99db879314d58e0064f02b481f668f45d0070Ashish Jangam				   reg_val);
3784c99db879314d58e0064f02b481f668f45d0070Ashish Jangam		if (ret < 0)
3884c99db879314d58e0064f02b481f668f45d0070Ashish Jangam			return ret;
3984c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	}
4084c99db879314d58e0064f02b481f668f45d0070Ashish Jangam
4184c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	return 0;
4284c99db879314d58e0064f02b481f668f45d0070Ashish Jangam}
4384c99db879314d58e0064f02b481f668f45d0070Ashish Jangam
4484c99db879314d58e0064f02b481f668f45d0070Ashish Jangamstatic int __devinit da9052_i2c_probe(struct i2c_client *client,
4584c99db879314d58e0064f02b481f668f45d0070Ashish Jangam				       const struct i2c_device_id *id)
4684c99db879314d58e0064f02b481f668f45d0070Ashish Jangam{
4784c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	struct da9052 *da9052;
4884c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	int ret;
4984c99db879314d58e0064f02b481f668f45d0070Ashish Jangam
5084c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	da9052 = kzalloc(sizeof(struct da9052), GFP_KERNEL);
5184c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	if (!da9052)
5284c99db879314d58e0064f02b481f668f45d0070Ashish Jangam		return -ENOMEM;
5384c99db879314d58e0064f02b481f668f45d0070Ashish Jangam
5484c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	if (!i2c_check_functionality(client->adapter,
5584c99db879314d58e0064f02b481f668f45d0070Ashish Jangam				     I2C_FUNC_SMBUS_BYTE_DATA)) {
5684c99db879314d58e0064f02b481f668f45d0070Ashish Jangam		dev_info(&client->dev, "Error in %s:i2c_check_functionality\n",
5784c99db879314d58e0064f02b481f668f45d0070Ashish Jangam			 __func__);
5884c99db879314d58e0064f02b481f668f45d0070Ashish Jangam		ret = -ENODEV;
5984c99db879314d58e0064f02b481f668f45d0070Ashish Jangam		goto err;
6084c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	}
6184c99db879314d58e0064f02b481f668f45d0070Ashish Jangam
6284c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	da9052->dev = &client->dev;
6384c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	da9052->chip_irq = client->irq;
6484c99db879314d58e0064f02b481f668f45d0070Ashish Jangam
6584c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	i2c_set_clientdata(client, da9052);
6684c99db879314d58e0064f02b481f668f45d0070Ashish Jangam
6784c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	da9052->regmap = regmap_init_i2c(client, &da9052_regmap_config);
6884c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	if (IS_ERR(da9052->regmap)) {
6984c99db879314d58e0064f02b481f668f45d0070Ashish Jangam		ret = PTR_ERR(da9052->regmap);
7084c99db879314d58e0064f02b481f668f45d0070Ashish Jangam		dev_err(&client->dev, "Failed to allocate register map: %d\n",
7184c99db879314d58e0064f02b481f668f45d0070Ashish Jangam			ret);
7284c99db879314d58e0064f02b481f668f45d0070Ashish Jangam		goto err;
7384c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	}
7484c99db879314d58e0064f02b481f668f45d0070Ashish Jangam
7584c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	ret = da9052_i2c_enable_multiwrite(da9052);
7684c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	if (ret < 0)
774d75dd61dfb53eaa286c54fb121e5b51b106c272Axel Lin		goto err_regmap;
7884c99db879314d58e0064f02b481f668f45d0070Ashish Jangam
7984c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	ret = da9052_device_init(da9052, id->driver_data);
8084c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	if (ret != 0)
814d75dd61dfb53eaa286c54fb121e5b51b106c272Axel Lin		goto err_regmap;
8284c99db879314d58e0064f02b481f668f45d0070Ashish Jangam
8384c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	return 0;
8484c99db879314d58e0064f02b481f668f45d0070Ashish Jangam
854d75dd61dfb53eaa286c54fb121e5b51b106c272Axel Linerr_regmap:
864d75dd61dfb53eaa286c54fb121e5b51b106c272Axel Lin	regmap_exit(da9052->regmap);
8784c99db879314d58e0064f02b481f668f45d0070Ashish Jangamerr:
8884c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	kfree(da9052);
8984c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	return ret;
9084c99db879314d58e0064f02b481f668f45d0070Ashish Jangam}
9184c99db879314d58e0064f02b481f668f45d0070Ashish Jangam
92bcc2d6d6fcbee3c07515837b522f6c242f3f99e4Dmitry Torokhovstatic int __devexit da9052_i2c_remove(struct i2c_client *client)
9384c99db879314d58e0064f02b481f668f45d0070Ashish Jangam{
9484c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	struct da9052 *da9052 = i2c_get_clientdata(client);
9584c99db879314d58e0064f02b481f668f45d0070Ashish Jangam
9684c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	da9052_device_exit(da9052);
974d75dd61dfb53eaa286c54fb121e5b51b106c272Axel Lin	regmap_exit(da9052->regmap);
9884c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	kfree(da9052);
9984c99db879314d58e0064f02b481f668f45d0070Ashish Jangam
10084c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	return 0;
10184c99db879314d58e0064f02b481f668f45d0070Ashish Jangam}
10284c99db879314d58e0064f02b481f668f45d0070Ashish Jangam
10384c99db879314d58e0064f02b481f668f45d0070Ashish Jangamstatic struct i2c_device_id da9052_i2c_id[] = {
10484c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	{"da9052", DA9052},
10584c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	{"da9053-aa", DA9053_AA},
10684c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	{"da9053-ba", DA9053_BA},
10784c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	{"da9053-bb", DA9053_BB},
10884c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	{}
10984c99db879314d58e0064f02b481f668f45d0070Ashish Jangam};
11084c99db879314d58e0064f02b481f668f45d0070Ashish Jangam
11184c99db879314d58e0064f02b481f668f45d0070Ashish Jangamstatic struct i2c_driver da9052_i2c_driver = {
11284c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	.probe = da9052_i2c_probe,
113bcc2d6d6fcbee3c07515837b522f6c242f3f99e4Dmitry Torokhov	.remove = __devexit_p(da9052_i2c_remove),
11484c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	.id_table = da9052_i2c_id,
11584c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	.driver = {
11684c99db879314d58e0064f02b481f668f45d0070Ashish Jangam		.name = "da9052",
11784c99db879314d58e0064f02b481f668f45d0070Ashish Jangam		.owner = THIS_MODULE,
11884c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	},
11984c99db879314d58e0064f02b481f668f45d0070Ashish Jangam};
12084c99db879314d58e0064f02b481f668f45d0070Ashish Jangam
12184c99db879314d58e0064f02b481f668f45d0070Ashish Jangamstatic int __init da9052_i2c_init(void)
12284c99db879314d58e0064f02b481f668f45d0070Ashish Jangam{
12384c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	int ret;
12484c99db879314d58e0064f02b481f668f45d0070Ashish Jangam
12584c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	ret = i2c_add_driver(&da9052_i2c_driver);
12684c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	if (ret != 0) {
12784c99db879314d58e0064f02b481f668f45d0070Ashish Jangam		pr_err("DA9052 I2C registration failed %d\n", ret);
12884c99db879314d58e0064f02b481f668f45d0070Ashish Jangam		return ret;
12984c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	}
13084c99db879314d58e0064f02b481f668f45d0070Ashish Jangam
13184c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	return 0;
13284c99db879314d58e0064f02b481f668f45d0070Ashish Jangam}
13384c99db879314d58e0064f02b481f668f45d0070Ashish Jangamsubsys_initcall(da9052_i2c_init);
13484c99db879314d58e0064f02b481f668f45d0070Ashish Jangam
13584c99db879314d58e0064f02b481f668f45d0070Ashish Jangamstatic void __exit da9052_i2c_exit(void)
13684c99db879314d58e0064f02b481f668f45d0070Ashish Jangam{
13784c99db879314d58e0064f02b481f668f45d0070Ashish Jangam	i2c_del_driver(&da9052_i2c_driver);
13884c99db879314d58e0064f02b481f668f45d0070Ashish Jangam}
13984c99db879314d58e0064f02b481f668f45d0070Ashish Jangammodule_exit(da9052_i2c_exit);
14084c99db879314d58e0064f02b481f668f45d0070Ashish Jangam
14184c99db879314d58e0064f02b481f668f45d0070Ashish JangamMODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
14284c99db879314d58e0064f02b481f668f45d0070Ashish JangamMODULE_DESCRIPTION("I2C driver for Dialog DA9052 PMIC");
14384c99db879314d58e0064f02b481f668f45d0070Ashish JangamMODULE_LICENSE("GPL");
144