da9052-i2c.c 3.8 KB
Newer Older
A
Ashish Jangam 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
/*
 * I2C access for DA9052 PMICs.
 *
 * Copyright(c) 2011 Dialog Semiconductor Ltd.
 *
 * Author: David Dajun Chen <dchen@diasemi.com>
 *
 * 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.
 *
 */

#include <linux/device.h>
#include <linux/module.h>
#include <linux/input.h>
#include <linux/mfd/core.h>
#include <linux/i2c.h>
#include <linux/err.h>

#include <linux/mfd/da9052/da9052.h>
#include <linux/mfd/da9052/reg.h>

25 26 27 28 29
#ifdef CONFIG_OF
#include <linux/of.h>
#include <linux/of_device.h>
#endif

A
Ashish Jangam 已提交
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
static int da9052_i2c_enable_multiwrite(struct da9052 *da9052)
{
	int reg_val, ret;

	ret = regmap_read(da9052->regmap, DA9052_CONTROL_B_REG, &reg_val);
	if (ret < 0)
		return ret;

	if (reg_val & DA9052_CONTROL_B_WRITEMODE) {
		reg_val &= ~DA9052_CONTROL_B_WRITEMODE;
		ret = regmap_write(da9052->regmap, DA9052_CONTROL_B_REG,
				   reg_val);
		if (ret < 0)
			return ret;
	}

	return 0;
}

49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
static struct i2c_device_id da9052_i2c_id[] = {
	{"da9052", DA9052},
	{"da9053-aa", DA9053_AA},
	{"da9053-ba", DA9053_BA},
	{"da9053-bb", DA9053_BB},
	{}
};

#ifdef CONFIG_OF
static const struct of_device_id dialog_dt_ids[] = {
	{ .compatible = "dlg,da9052", .data = &da9052_i2c_id[0] },
	{ .compatible = "dlg,da9053-aa", .data = &da9052_i2c_id[1] },
	{ .compatible = "dlg,da9053-ab", .data = &da9052_i2c_id[2] },
	{ .compatible = "dlg,da9053-bb", .data = &da9052_i2c_id[3] },
	{ /* sentinel */ }
};
#endif

A
Ashish Jangam 已提交
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
static int __devinit da9052_i2c_probe(struct i2c_client *client,
				       const struct i2c_device_id *id)
{
	struct da9052 *da9052;
	int ret;

	da9052 = kzalloc(sizeof(struct da9052), GFP_KERNEL);
	if (!da9052)
		return -ENOMEM;

	if (!i2c_check_functionality(client->adapter,
				     I2C_FUNC_SMBUS_BYTE_DATA)) {
		dev_info(&client->dev, "Error in %s:i2c_check_functionality\n",
			 __func__);
		ret = -ENODEV;
		goto err;
	}

	da9052->dev = &client->dev;
	da9052->chip_irq = client->irq;

	i2c_set_clientdata(client, da9052);

	da9052->regmap = regmap_init_i2c(client, &da9052_regmap_config);
	if (IS_ERR(da9052->regmap)) {
		ret = PTR_ERR(da9052->regmap);
		dev_err(&client->dev, "Failed to allocate register map: %d\n",
			ret);
		goto err;
	}

	ret = da9052_i2c_enable_multiwrite(da9052);
	if (ret < 0)
100
		goto err_regmap;
A
Ashish Jangam 已提交
101

102 103 104 105 106
#ifdef CONFIG_OF
	if (!id) {
		struct device_node *np = client->dev.of_node;
		const struct of_device_id *deviceid;

107
		deviceid = of_match_node(dialog_dt_ids, np);
108 109 110 111 112 113 114 115 116 117
		id = (const struct i2c_device_id *)deviceid->data;
	}
#endif

	if (!id) {
		ret = -ENODEV;
		dev_err(&client->dev, "id is null.\n");
		goto err_regmap;
	}

A
Ashish Jangam 已提交
118 119
	ret = da9052_device_init(da9052, id->driver_data);
	if (ret != 0)
120
		goto err_regmap;
A
Ashish Jangam 已提交
121 122 123

	return 0;

124 125
err_regmap:
	regmap_exit(da9052->regmap);
A
Ashish Jangam 已提交
126 127 128 129 130
err:
	kfree(da9052);
	return ret;
}

131
static int __devexit da9052_i2c_remove(struct i2c_client *client)
A
Ashish Jangam 已提交
132 133 134 135
{
	struct da9052 *da9052 = i2c_get_clientdata(client);

	da9052_device_exit(da9052);
136
	regmap_exit(da9052->regmap);
A
Ashish Jangam 已提交
137 138 139 140 141 142 143
	kfree(da9052);

	return 0;
}

static struct i2c_driver da9052_i2c_driver = {
	.probe = da9052_i2c_probe,
144
	.remove = __devexit_p(da9052_i2c_remove),
A
Ashish Jangam 已提交
145 146 147 148
	.id_table = da9052_i2c_id,
	.driver = {
		.name = "da9052",
		.owner = THIS_MODULE,
149 150 151
#ifdef CONFIG_OF
		.of_match_table = dialog_dt_ids,
#endif
A
Ashish Jangam 已提交
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
	},
};

static int __init da9052_i2c_init(void)
{
	int ret;

	ret = i2c_add_driver(&da9052_i2c_driver);
	if (ret != 0) {
		pr_err("DA9052 I2C registration failed %d\n", ret);
		return ret;
	}

	return 0;
}
subsys_initcall(da9052_i2c_init);

static void __exit da9052_i2c_exit(void)
{
	i2c_del_driver(&da9052_i2c_driver);
}
module_exit(da9052_i2c_exit);

MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
MODULE_DESCRIPTION("I2C driver for Dialog DA9052 PMIC");
MODULE_LICENSE("GPL");