Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1/* da9063-i2c.c: Interrupt support for Dialog DA9063
  2 *
  3 * Copyright 2012 Dialog Semiconductor Ltd.
  4 * Copyright 2013 Philipp Zabel, Pengutronix
  5 *
  6 * Author: Krystian Garbaciak, Dialog Semiconductor
  7 *
  8 *  This program is free software; you can redistribute  it and/or modify it
  9 *  under  the terms of  the GNU General  Public License as published by the
 10 *  Free Software Foundation;  either version 2 of the  License, or (at your
 11 *  option) any later version.
 12 *
 13 */
 14
 15#include <linux/kernel.h>
 16#include <linux/module.h>
 17#include <linux/i2c.h>
 18#include <linux/regmap.h>
 19#include <linux/delay.h>
 20#include <linux/slab.h>
 21#include <linux/err.h>
 22
 23#include <linux/mfd/core.h>
 24#include <linux/mfd/da9063/core.h>
 25#include <linux/mfd/da9063/pdata.h>
 26#include <linux/mfd/da9063/registers.h>
 27
 28#include <linux/of.h>
 29#include <linux/regulator/of_regulator.h>
 30
 31static const struct regmap_range da9063_ad_readable_ranges[] = {
 32	{
 33		.range_min = DA9063_REG_PAGE_CON,
 34		.range_max = DA9063_AD_REG_SECOND_D,
 35	}, {
 36		.range_min = DA9063_REG_SEQ,
 37		.range_max = DA9063_REG_ID_32_31,
 38	}, {
 39		.range_min = DA9063_REG_SEQ_A,
 40		.range_max = DA9063_REG_AUTO3_LOW,
 41	}, {
 42		.range_min = DA9063_REG_T_OFFSET,
 43		.range_max = DA9063_AD_REG_GP_ID_19,
 44	}, {
 45		.range_min = DA9063_REG_CHIP_ID,
 46		.range_max = DA9063_REG_CHIP_VARIANT,
 47	},
 48};
 49
 50static const struct regmap_range da9063_ad_writeable_ranges[] = {
 51	{
 52		.range_min = DA9063_REG_PAGE_CON,
 53		.range_max = DA9063_REG_PAGE_CON,
 54	}, {
 55		.range_min = DA9063_REG_FAULT_LOG,
 56		.range_max = DA9063_REG_VSYS_MON,
 57	}, {
 58		.range_min = DA9063_REG_COUNT_S,
 59		.range_max = DA9063_AD_REG_ALARM_Y,
 60	}, {
 61		.range_min = DA9063_REG_SEQ,
 62		.range_max = DA9063_REG_ID_32_31,
 63	}, {
 64		.range_min = DA9063_REG_SEQ_A,
 65		.range_max = DA9063_REG_AUTO3_LOW,
 66	}, {
 67		.range_min = DA9063_REG_CONFIG_I,
 68		.range_max = DA9063_AD_REG_MON_REG_4,
 69	}, {
 70		.range_min = DA9063_AD_REG_GP_ID_0,
 71		.range_max = DA9063_AD_REG_GP_ID_19,
 72	},
 73};
 74
 75static const struct regmap_range da9063_ad_volatile_ranges[] = {
 76	{
 77		.range_min = DA9063_REG_PAGE_CON,
 78		.range_max = DA9063_REG_EVENT_D,
 79	}, {
 80		.range_min = DA9063_REG_CONTROL_A,
 81		.range_max = DA9063_REG_CONTROL_B,
 82	}, {
 83		.range_min = DA9063_REG_CONTROL_E,
 84		.range_max = DA9063_REG_CONTROL_F,
 85	}, {
 86		.range_min = DA9063_REG_BCORE2_CONT,
 87		.range_max = DA9063_REG_LDO11_CONT,
 88	}, {
 89		.range_min = DA9063_REG_DVC_1,
 90		.range_max = DA9063_REG_ADC_MAN,
 91	}, {
 92		.range_min = DA9063_REG_ADC_RES_L,
 93		.range_max = DA9063_AD_REG_SECOND_D,
 94	}, {
 95		.range_min = DA9063_REG_SEQ,
 96		.range_max = DA9063_REG_SEQ,
 97	}, {
 98		.range_min = DA9063_REG_EN_32K,
 99		.range_max = DA9063_REG_EN_32K,
100	}, {
101		.range_min = DA9063_AD_REG_MON_REG_5,
102		.range_max = DA9063_AD_REG_MON_REG_6,
103	},
104};
105
106static const struct regmap_access_table da9063_ad_readable_table = {
107	.yes_ranges = da9063_ad_readable_ranges,
108	.n_yes_ranges = ARRAY_SIZE(da9063_ad_readable_ranges),
109};
110
111static const struct regmap_access_table da9063_ad_writeable_table = {
112	.yes_ranges = da9063_ad_writeable_ranges,
113	.n_yes_ranges = ARRAY_SIZE(da9063_ad_writeable_ranges),
114};
115
116static const struct regmap_access_table da9063_ad_volatile_table = {
117	.yes_ranges = da9063_ad_volatile_ranges,
118	.n_yes_ranges = ARRAY_SIZE(da9063_ad_volatile_ranges),
119};
120
121static const struct regmap_range da9063_bb_readable_ranges[] = {
122	{
123		.range_min = DA9063_REG_PAGE_CON,
124		.range_max = DA9063_BB_REG_SECOND_D,
125	}, {
126		.range_min = DA9063_REG_SEQ,
127		.range_max = DA9063_REG_ID_32_31,
128	}, {
129		.range_min = DA9063_REG_SEQ_A,
130		.range_max = DA9063_REG_AUTO3_LOW,
131	}, {
132		.range_min = DA9063_REG_T_OFFSET,
133		.range_max = DA9063_BB_REG_GP_ID_19,
134	}, {
135		.range_min = DA9063_REG_CHIP_ID,
136		.range_max = DA9063_REG_CHIP_VARIANT,
137	},
138};
139
140static const struct regmap_range da9063_bb_writeable_ranges[] = {
141	{
142		.range_min = DA9063_REG_PAGE_CON,
143		.range_max = DA9063_REG_PAGE_CON,
144	}, {
145		.range_min = DA9063_REG_FAULT_LOG,
146		.range_max = DA9063_REG_VSYS_MON,
147	}, {
148		.range_min = DA9063_REG_COUNT_S,
149		.range_max = DA9063_BB_REG_ALARM_Y,
150	}, {
151		.range_min = DA9063_REG_SEQ,
152		.range_max = DA9063_REG_ID_32_31,
153	}, {
154		.range_min = DA9063_REG_SEQ_A,
155		.range_max = DA9063_REG_AUTO3_LOW,
156	}, {
157		.range_min = DA9063_REG_CONFIG_I,
158		.range_max = DA9063_BB_REG_MON_REG_4,
159	}, {
160		.range_min = DA9063_BB_REG_GP_ID_0,
161		.range_max = DA9063_BB_REG_GP_ID_19,
162	},
163};
164
165static const struct regmap_range da9063_bb_volatile_ranges[] = {
166	{
167		.range_min = DA9063_REG_PAGE_CON,
168		.range_max = DA9063_REG_EVENT_D,
169	}, {
170		.range_min = DA9063_REG_CONTROL_A,
171		.range_max = DA9063_REG_CONTROL_B,
172	}, {
173		.range_min = DA9063_REG_CONTROL_E,
174		.range_max = DA9063_REG_CONTROL_F,
175	}, {
176		.range_min = DA9063_REG_BCORE2_CONT,
177		.range_max = DA9063_REG_LDO11_CONT,
178	}, {
179		.range_min = DA9063_REG_DVC_1,
180		.range_max = DA9063_REG_ADC_MAN,
181	}, {
182		.range_min = DA9063_REG_ADC_RES_L,
183		.range_max = DA9063_BB_REG_SECOND_D,
184	}, {
185		.range_min = DA9063_REG_SEQ,
186		.range_max = DA9063_REG_SEQ,
187	}, {
188		.range_min = DA9063_REG_EN_32K,
189		.range_max = DA9063_REG_EN_32K,
190	}, {
191		.range_min = DA9063_BB_REG_MON_REG_5,
192		.range_max = DA9063_BB_REG_MON_REG_6,
193	},
194};
195
196static const struct regmap_access_table da9063_bb_readable_table = {
197	.yes_ranges = da9063_bb_readable_ranges,
198	.n_yes_ranges = ARRAY_SIZE(da9063_bb_readable_ranges),
199};
200
201static const struct regmap_access_table da9063_bb_writeable_table = {
202	.yes_ranges = da9063_bb_writeable_ranges,
203	.n_yes_ranges = ARRAY_SIZE(da9063_bb_writeable_ranges),
204};
205
206static const struct regmap_access_table da9063_bb_volatile_table = {
207	.yes_ranges = da9063_bb_volatile_ranges,
208	.n_yes_ranges = ARRAY_SIZE(da9063_bb_volatile_ranges),
209};
210
211static const struct regmap_range_cfg da9063_range_cfg[] = {
212	{
213		.range_min = DA9063_REG_PAGE_CON,
214		.range_max = DA9063_REG_CHIP_VARIANT,
215		.selector_reg = DA9063_REG_PAGE_CON,
216		.selector_mask = 1 << DA9063_I2C_PAGE_SEL_SHIFT,
217		.selector_shift = DA9063_I2C_PAGE_SEL_SHIFT,
218		.window_start = 0,
219		.window_len = 256,
220	}
221};
222
223static struct regmap_config da9063_regmap_config = {
224	.reg_bits = 8,
225	.val_bits = 8,
226	.ranges = da9063_range_cfg,
227	.num_ranges = ARRAY_SIZE(da9063_range_cfg),
228	.max_register = DA9063_REG_CHIP_VARIANT,
229
230	.cache_type = REGCACHE_RBTREE,
231};
232
233static const struct of_device_id da9063_dt_ids[] = {
234	{ .compatible = "dlg,da9063", },
235	{ }
236};
237MODULE_DEVICE_TABLE(of, da9063_dt_ids);
238static int da9063_i2c_probe(struct i2c_client *i2c,
239	const struct i2c_device_id *id)
240{
241	struct da9063 *da9063;
242	int ret;
243
244	da9063 = devm_kzalloc(&i2c->dev, sizeof(struct da9063), GFP_KERNEL);
245	if (da9063 == NULL)
246		return -ENOMEM;
247
248	i2c_set_clientdata(i2c, da9063);
249	da9063->dev = &i2c->dev;
250	da9063->chip_irq = i2c->irq;
251
252	if (da9063->variant_code == PMIC_DA9063_AD) {
253		da9063_regmap_config.rd_table = &da9063_ad_readable_table;
254		da9063_regmap_config.wr_table = &da9063_ad_writeable_table;
255		da9063_regmap_config.volatile_table = &da9063_ad_volatile_table;
256	} else {
257		da9063_regmap_config.rd_table = &da9063_bb_readable_table;
258		da9063_regmap_config.wr_table = &da9063_bb_writeable_table;
259		da9063_regmap_config.volatile_table = &da9063_bb_volatile_table;
260	}
261
262	da9063->regmap = devm_regmap_init_i2c(i2c, &da9063_regmap_config);
263	if (IS_ERR(da9063->regmap)) {
264		ret = PTR_ERR(da9063->regmap);
265		dev_err(da9063->dev, "Failed to allocate register map: %d\n",
266			ret);
267		return ret;
268	}
269
270	return da9063_device_init(da9063, i2c->irq);
271}
272
273static int da9063_i2c_remove(struct i2c_client *i2c)
274{
275	struct da9063 *da9063 = i2c_get_clientdata(i2c);
276
277	da9063_device_exit(da9063);
278
279	return 0;
280}
281
282static const struct i2c_device_id da9063_i2c_id[] = {
283	{"da9063", PMIC_DA9063},
284	{},
285};
286MODULE_DEVICE_TABLE(i2c, da9063_i2c_id);
287
288static struct i2c_driver da9063_i2c_driver = {
289	.driver = {
290		.name = "da9063",
291		.of_match_table = of_match_ptr(da9063_dt_ids),
292	},
293	.probe    = da9063_i2c_probe,
294	.remove   = da9063_i2c_remove,
295	.id_table = da9063_i2c_id,
296};
297
298module_i2c_driver(da9063_i2c_driver);