Blame view

drivers/mfd/max8998.c 8.95 KB
d7d8d7a24   Krzysztof Kozlowski   mfd: maxim: Add S...
1
2
3
4
5
6
7
  // SPDX-License-Identifier: GPL-2.0+
  //
  // max8998.c - mfd core driver for the Maxim 8998
  //
  //  Copyright (C) 2009-2010 Samsung Electronics
  //  Kyungmin Park <kyungmin.park@samsung.com>
  //  Marek Szyprowski <m.szyprowski@samsung.com>
156f25285   Kyungmin Park   drivers: regulato...
8

ee999fb3f   Tomasz Figa   mfd: max8998: Add...
9
  #include <linux/err.h>
156f25285   Kyungmin Park   drivers: regulato...
10
11
12
  #include <linux/init.h>
  #include <linux/slab.h>
  #include <linux/i2c.h>
cdd137c9c   MyungJoo Ham   mfd: MAX8998/LP39...
13
  #include <linux/interrupt.h>
ee999fb3f   Tomasz Figa   mfd: max8998: Add...
14
15
  #include <linux/of.h>
  #include <linux/of_irq.h>
cdd137c9c   MyungJoo Ham   mfd: MAX8998/LP39...
16
  #include <linux/pm_runtime.h>
156f25285   Kyungmin Park   drivers: regulato...
17
18
19
20
  #include <linux/mutex.h>
  #include <linux/mfd/core.h>
  #include <linux/mfd/max8998.h>
  #include <linux/mfd/max8998-private.h>
9b16c0a43   Joonyoung Shim   rtc: Add MAX8998 ...
21
  #define RTC_I2C_ADDR		(0x0c >> 1)
7c0517b17   Geert Uytterhoeven   mfd: maxim: Const...
22
  static const struct mfd_cell max8998_devs[] = {
156f25285   Kyungmin Park   drivers: regulato...
23
24
  	{
  		.name = "max8998-pmic",
9b16c0a43   Joonyoung Shim   rtc: Add MAX8998 ...
25
26
  	}, {
  		.name = "max8998-rtc",
bb4ce9708   Donggeun Kim   power_supply: Add...
27
28
  	}, {
  		.name = "max8998-battery",
9b16c0a43   Joonyoung Shim   rtc: Add MAX8998 ...
29
  	},
156f25285   Kyungmin Park   drivers: regulato...
30
  };
7c0517b17   Geert Uytterhoeven   mfd: maxim: Const...
31
  static const struct mfd_cell lp3974_devs[] = {
337ce5d1c   MyungJoo Ham   mfd: Support LP39...
32
33
34
35
36
37
  	{
  		.name = "lp3974-pmic",
  	}, {
  		.name = "lp3974-rtc",
  	},
  };
676e02d7a   Joonyoung Shim   mfd: Use i2c_clie...
38
  int max8998_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest)
156f25285   Kyungmin Park   drivers: regulato...
39
  {
676e02d7a   Joonyoung Shim   mfd: Use i2c_clie...
40
  	struct max8998_dev *max8998 = i2c_get_clientdata(i2c);
156f25285   Kyungmin Park   drivers: regulato...
41
42
43
  	int ret;
  
  	mutex_lock(&max8998->iolock);
676e02d7a   Joonyoung Shim   mfd: Use i2c_clie...
44
  	ret = i2c_smbus_read_byte_data(i2c, reg);
156f25285   Kyungmin Park   drivers: regulato...
45
46
47
48
49
50
51
52
  	mutex_unlock(&max8998->iolock);
  	if (ret < 0)
  		return ret;
  
  	ret &= 0xff;
  	*dest = ret;
  	return 0;
  }
676e02d7a   Joonyoung Shim   mfd: Use i2c_clie...
53
  EXPORT_SYMBOL(max8998_read_reg);
156f25285   Kyungmin Park   drivers: regulato...
54

2c7e6f579   Joonyoung Shim   mfd: Add MAX8998 ...
55
56
57
58
59
60
61
62
63
64
65
66
67
68
  int max8998_bulk_read(struct i2c_client *i2c, u8 reg, int count, u8 *buf)
  {
  	struct max8998_dev *max8998 = i2c_get_clientdata(i2c);
  	int ret;
  
  	mutex_lock(&max8998->iolock);
  	ret = i2c_smbus_read_i2c_block_data(i2c, reg, count, buf);
  	mutex_unlock(&max8998->iolock);
  	if (ret < 0)
  		return ret;
  
  	return 0;
  }
  EXPORT_SYMBOL(max8998_bulk_read);
676e02d7a   Joonyoung Shim   mfd: Use i2c_clie...
69
  int max8998_write_reg(struct i2c_client *i2c, u8 reg, u8 value)
156f25285   Kyungmin Park   drivers: regulato...
70
  {
676e02d7a   Joonyoung Shim   mfd: Use i2c_clie...
71
  	struct max8998_dev *max8998 = i2c_get_clientdata(i2c);
156f25285   Kyungmin Park   drivers: regulato...
72
73
74
  	int ret;
  
  	mutex_lock(&max8998->iolock);
676e02d7a   Joonyoung Shim   mfd: Use i2c_clie...
75
  	ret = i2c_smbus_write_byte_data(i2c, reg, value);
156f25285   Kyungmin Park   drivers: regulato...
76
77
78
  	mutex_unlock(&max8998->iolock);
  	return ret;
  }
676e02d7a   Joonyoung Shim   mfd: Use i2c_clie...
79
  EXPORT_SYMBOL(max8998_write_reg);
156f25285   Kyungmin Park   drivers: regulato...
80

9b16c0a43   Joonyoung Shim   rtc: Add MAX8998 ...
81
82
83
84
85
86
87
88
89
90
91
92
93
94
  int max8998_bulk_write(struct i2c_client *i2c, u8 reg, int count, u8 *buf)
  {
  	struct max8998_dev *max8998 = i2c_get_clientdata(i2c);
  	int ret;
  
  	mutex_lock(&max8998->iolock);
  	ret = i2c_smbus_write_i2c_block_data(i2c, reg, count, buf);
  	mutex_unlock(&max8998->iolock);
  	if (ret < 0)
  		return ret;
  
  	return 0;
  }
  EXPORT_SYMBOL(max8998_bulk_write);
676e02d7a   Joonyoung Shim   mfd: Use i2c_clie...
95
  int max8998_update_reg(struct i2c_client *i2c, u8 reg, u8 val, u8 mask)
156f25285   Kyungmin Park   drivers: regulato...
96
  {
676e02d7a   Joonyoung Shim   mfd: Use i2c_clie...
97
  	struct max8998_dev *max8998 = i2c_get_clientdata(i2c);
156f25285   Kyungmin Park   drivers: regulato...
98
99
100
  	int ret;
  
  	mutex_lock(&max8998->iolock);
676e02d7a   Joonyoung Shim   mfd: Use i2c_clie...
101
  	ret = i2c_smbus_read_byte_data(i2c, reg);
156f25285   Kyungmin Park   drivers: regulato...
102
103
104
  	if (ret >= 0) {
  		u8 old_val = ret & 0xff;
  		u8 new_val = (val & mask) | (old_val & (~mask));
676e02d7a   Joonyoung Shim   mfd: Use i2c_clie...
105
  		ret = i2c_smbus_write_byte_data(i2c, reg, new_val);
156f25285   Kyungmin Park   drivers: regulato...
106
107
108
109
  	}
  	mutex_unlock(&max8998->iolock);
  	return ret;
  }
676e02d7a   Joonyoung Shim   mfd: Use i2c_clie...
110
  EXPORT_SYMBOL(max8998_update_reg);
156f25285   Kyungmin Park   drivers: regulato...
111

ee999fb3f   Tomasz Figa   mfd: max8998: Add...
112
  #ifdef CONFIG_OF
e920574d7   Krzysztof Kozlowski   mfd: max8998: Mak...
113
  static const struct of_device_id max8998_dt_match[] = {
ee999fb3f   Tomasz Figa   mfd: max8998: Add...
114
115
116
117
118
  	{ .compatible = "maxim,max8998", .data = (void *)TYPE_MAX8998 },
  	{ .compatible = "national,lp3974", .data = (void *)TYPE_LP3974 },
  	{ .compatible = "ti,lp3974", .data = (void *)TYPE_LP3974 },
  	{},
  };
ee999fb3f   Tomasz Figa   mfd: max8998: Add...
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
  #endif
  
  /*
   * Only the common platform data elements for max8998 are parsed here from the
   * device tree. Other sub-modules of max8998 such as pmic, rtc and others have
   * to parse their own platform data elements from device tree.
   *
   * The max8998 platform data structure is instantiated here and the drivers for
   * the sub-modules need not instantiate another instance while parsing their
   * platform data.
   */
  static struct max8998_platform_data *max8998_i2c_parse_dt_pdata(
  							struct device *dev)
  {
  	struct max8998_platform_data *pd;
  
  	pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
  	if (!pd)
  		return ERR_PTR(-ENOMEM);
  
  	pd->ono = irq_of_parse_and_map(dev->of_node, 1);
  
  	/*
  	 * ToDo: the 'wakeup' member in the platform data is more of a linux
  	 * specfic information. Hence, there is no binding for that yet and
  	 * not parsed here.
  	 */
  	return pd;
  }
8bace2d5b   Lee Jones   mfd: max8998: Nat...
148
  static inline unsigned long max8998_i2c_get_driver_data(struct i2c_client *i2c,
ee999fb3f   Tomasz Figa   mfd: max8998: Add...
149
150
151
152
153
  						const struct i2c_device_id *id)
  {
  	if (IS_ENABLED(CONFIG_OF) && i2c->dev.of_node) {
  		const struct of_device_id *match;
  		match = of_match_node(max8998_dt_match, i2c->dev.of_node);
8bace2d5b   Lee Jones   mfd: max8998: Nat...
154
  		return (unsigned long)match->data;
ee999fb3f   Tomasz Figa   mfd: max8998: Add...
155
  	}
8bace2d5b   Lee Jones   mfd: max8998: Nat...
156
  	return id->driver_data;
ee999fb3f   Tomasz Figa   mfd: max8998: Add...
157
  }
156f25285   Kyungmin Park   drivers: regulato...
158
159
160
  static int max8998_i2c_probe(struct i2c_client *i2c,
  			    const struct i2c_device_id *id)
  {
334a41ce9   Jingoo Han   mfd: Use dev_get_...
161
  	struct max8998_platform_data *pdata = dev_get_platdata(&i2c->dev);
156f25285   Kyungmin Park   drivers: regulato...
162
163
  	struct max8998_dev *max8998;
  	int ret = 0;
0010dd388   Jingoo Han   mfd: max8998: Use...
164
165
  	max8998 = devm_kzalloc(&i2c->dev, sizeof(struct max8998_dev),
  				GFP_KERNEL);
8f1f151ed   Axel Lin   mfd: max8998 - fi...
166
  	if (max8998 == NULL)
156f25285   Kyungmin Park   drivers: regulato...
167
  		return -ENOMEM;
156f25285   Kyungmin Park   drivers: regulato...
168

ee999fb3f   Tomasz Figa   mfd: max8998: Add...
169
170
  	if (IS_ENABLED(CONFIG_OF) && i2c->dev.of_node) {
  		pdata = max8998_i2c_parse_dt_pdata(&i2c->dev);
2042f3c29   Christophe JAILLET   mfd: max8998: Fix...
171
172
  		if (IS_ERR(pdata))
  			return PTR_ERR(pdata);
ee999fb3f   Tomasz Figa   mfd: max8998: Add...
173
  	}
156f25285   Kyungmin Park   drivers: regulato...
174
175
  	i2c_set_clientdata(i2c, max8998);
  	max8998->dev = &i2c->dev;
676e02d7a   Joonyoung Shim   mfd: Use i2c_clie...
176
  	max8998->i2c = i2c;
2c7e6f579   Joonyoung Shim   mfd: Add MAX8998 ...
177
  	max8998->irq = i2c->irq;
ee999fb3f   Tomasz Figa   mfd: max8998: Add...
178
179
  	max8998->type = max8998_i2c_get_driver_data(i2c, id);
  	max8998->pdata = pdata;
2c7e6f579   Joonyoung Shim   mfd: Add MAX8998 ...
180
181
182
  	if (pdata) {
  		max8998->ono = pdata->ono;
  		max8998->irq_base = pdata->irq_base;
cdd137c9c   MyungJoo Ham   mfd: MAX8998/LP39...
183
  		max8998->wakeup = pdata->wakeup;
2c7e6f579   Joonyoung Shim   mfd: Add MAX8998 ...
184
  	}
156f25285   Kyungmin Park   drivers: regulato...
185
  	mutex_init(&max8998->iolock);
7a99c8f33   Wolfram Sang   mfd: max8998: Con...
186
187
  	max8998->rtc = i2c_new_dummy_device(i2c->adapter, RTC_I2C_ADDR);
  	if (IS_ERR(max8998->rtc)) {
ed26f87b9   Krzysztof Kozlowski   mfd: max8998: Fix...
188
189
  		dev_err(&i2c->dev, "Failed to allocate I2C device for RTC
  ");
7a99c8f33   Wolfram Sang   mfd: max8998: Con...
190
  		return PTR_ERR(max8998->rtc);
ed26f87b9   Krzysztof Kozlowski   mfd: max8998: Fix...
191
  	}
9b16c0a43   Joonyoung Shim   rtc: Add MAX8998 ...
192
  	i2c_set_clientdata(max8998->rtc, max8998);
2c7e6f579   Joonyoung Shim   mfd: Add MAX8998 ...
193
  	max8998_irq_init(max8998);
cdd137c9c   MyungJoo Ham   mfd: MAX8998/LP39...
194
  	pm_runtime_set_active(max8998->dev);
ee999fb3f   Tomasz Figa   mfd: max8998: Add...
195
  	switch (max8998->type) {
337ce5d1c   MyungJoo Ham   mfd: Support LP39...
196
197
  	case TYPE_LP3974:
  		ret = mfd_add_devices(max8998->dev, -1,
0848c94fb   Mark Brown   mfd: core: Push i...
198
199
  				      lp3974_devs, ARRAY_SIZE(lp3974_devs),
  				      NULL, 0, NULL);
337ce5d1c   MyungJoo Ham   mfd: Support LP39...
200
201
202
  		break;
  	case TYPE_MAX8998:
  		ret = mfd_add_devices(max8998->dev, -1,
0848c94fb   Mark Brown   mfd: core: Push i...
203
204
  				      max8998_devs, ARRAY_SIZE(max8998_devs),
  				      NULL, 0, NULL);
337ce5d1c   MyungJoo Ham   mfd: Support LP39...
205
206
207
208
  		break;
  	default:
  		ret = -EINVAL;
  	}
156f25285   Kyungmin Park   drivers: regulato...
209
210
  	if (ret < 0)
  		goto err;
7ef73598d   Jonghwan Choi   mfd: Use standard...
211
  	device_init_wakeup(max8998->dev, max8998->wakeup);
156f25285   Kyungmin Park   drivers: regulato...
212
213
214
215
  	return ret;
  
  err:
  	mfd_remove_devices(max8998->dev);
7484552eb   Axel Lin   mfd: Fix resource...
216
217
  	max8998_irq_exit(max8998);
  	i2c_unregister_device(max8998->rtc);
156f25285   Kyungmin Park   drivers: regulato...
218
219
  	return ret;
  }
156f25285   Kyungmin Park   drivers: regulato...
220
  static const struct i2c_device_id max8998_i2c_id[] = {
509bd4764   Lukasz Majewski   mfd: Support for ...
221
222
  	{ "max8998", TYPE_MAX8998 },
  	{ "lp3974", TYPE_LP3974},
f8539ddcb   Kyungmin Park   mfd: LP3974 PMIC ...
223
  	{ }
156f25285   Kyungmin Park   drivers: regulato...
224
  };
156f25285   Kyungmin Park   drivers: regulato...
225

cdd137c9c   MyungJoo Ham   mfd: MAX8998/LP39...
226
227
  static int max8998_suspend(struct device *dev)
  {
1b5420e1f   Geliang Tang   mfd: Use to_i2c_c...
228
  	struct i2c_client *i2c = to_i2c_client(dev);
cdd137c9c   MyungJoo Ham   mfd: MAX8998/LP39...
229
  	struct max8998_dev *max8998 = i2c_get_clientdata(i2c);
7ef73598d   Jonghwan Choi   mfd: Use standard...
230
  	if (device_may_wakeup(dev))
d5bb12216   Thomas Gleixner   mfd: Cleanup irq ...
231
  		irq_set_irq_wake(max8998->irq, 1);
cdd137c9c   MyungJoo Ham   mfd: MAX8998/LP39...
232
233
234
235
236
  	return 0;
  }
  
  static int max8998_resume(struct device *dev)
  {
1b5420e1f   Geliang Tang   mfd: Use to_i2c_c...
237
  	struct i2c_client *i2c = to_i2c_client(dev);
cdd137c9c   MyungJoo Ham   mfd: MAX8998/LP39...
238
  	struct max8998_dev *max8998 = i2c_get_clientdata(i2c);
7ef73598d   Jonghwan Choi   mfd: Use standard...
239
  	if (device_may_wakeup(dev))
d5bb12216   Thomas Gleixner   mfd: Cleanup irq ...
240
  		irq_set_irq_wake(max8998->irq, 0);
cdd137c9c   MyungJoo Ham   mfd: MAX8998/LP39...
241
242
243
244
245
246
247
248
249
250
251
252
253
  	/*
  	 * In LP3974, if IRQ registers are not "read & clear"
  	 * when it's set during sleep, the interrupt becomes
  	 * disabled.
  	 */
  	return max8998_irq_resume(i2c_get_clientdata(i2c));
  }
  
  struct max8998_reg_dump {
  	u8	addr;
  	u8	val;
  };
  #define SAVE_ITEM(x)	{ .addr = (x), .val = 0x0, }
44be0a40d   Mark Brown   mfd: Staticise no...
254
  static struct max8998_reg_dump max8998_dump[] = {
cdd137c9c   MyungJoo Ham   mfd: MAX8998/LP39...
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
  	SAVE_ITEM(MAX8998_REG_IRQM1),
  	SAVE_ITEM(MAX8998_REG_IRQM2),
  	SAVE_ITEM(MAX8998_REG_IRQM3),
  	SAVE_ITEM(MAX8998_REG_IRQM4),
  	SAVE_ITEM(MAX8998_REG_STATUSM1),
  	SAVE_ITEM(MAX8998_REG_STATUSM2),
  	SAVE_ITEM(MAX8998_REG_CHGR1),
  	SAVE_ITEM(MAX8998_REG_CHGR2),
  	SAVE_ITEM(MAX8998_REG_LDO_ACTIVE_DISCHARGE1),
  	SAVE_ITEM(MAX8998_REG_LDO_ACTIVE_DISCHARGE1),
  	SAVE_ITEM(MAX8998_REG_BUCK_ACTIVE_DISCHARGE3),
  	SAVE_ITEM(MAX8998_REG_ONOFF1),
  	SAVE_ITEM(MAX8998_REG_ONOFF2),
  	SAVE_ITEM(MAX8998_REG_ONOFF3),
  	SAVE_ITEM(MAX8998_REG_ONOFF4),
  	SAVE_ITEM(MAX8998_REG_BUCK1_VOLTAGE1),
  	SAVE_ITEM(MAX8998_REG_BUCK1_VOLTAGE2),
  	SAVE_ITEM(MAX8998_REG_BUCK1_VOLTAGE3),
  	SAVE_ITEM(MAX8998_REG_BUCK1_VOLTAGE4),
  	SAVE_ITEM(MAX8998_REG_BUCK2_VOLTAGE1),
  	SAVE_ITEM(MAX8998_REG_BUCK2_VOLTAGE2),
  	SAVE_ITEM(MAX8998_REG_LDO2_LDO3),
  	SAVE_ITEM(MAX8998_REG_LDO4),
  	SAVE_ITEM(MAX8998_REG_LDO5),
  	SAVE_ITEM(MAX8998_REG_LDO6),
  	SAVE_ITEM(MAX8998_REG_LDO7),
  	SAVE_ITEM(MAX8998_REG_LDO8_LDO9),
  	SAVE_ITEM(MAX8998_REG_LDO10_LDO11),
  	SAVE_ITEM(MAX8998_REG_LDO12),
  	SAVE_ITEM(MAX8998_REG_LDO13),
  	SAVE_ITEM(MAX8998_REG_LDO14),
  	SAVE_ITEM(MAX8998_REG_LDO15),
  	SAVE_ITEM(MAX8998_REG_LDO16),
  	SAVE_ITEM(MAX8998_REG_LDO17),
  	SAVE_ITEM(MAX8998_REG_BKCHR),
  	SAVE_ITEM(MAX8998_REG_LBCNFG1),
  	SAVE_ITEM(MAX8998_REG_LBCNFG2),
  };
  /* Save registers before hibernation */
  static int max8998_freeze(struct device *dev)
  {
1b5420e1f   Geliang Tang   mfd: Use to_i2c_c...
296
  	struct i2c_client *i2c = to_i2c_client(dev);
cdd137c9c   MyungJoo Ham   mfd: MAX8998/LP39...
297
298
299
300
301
302
303
304
305
306
307
308
  	int i;
  
  	for (i = 0; i < ARRAY_SIZE(max8998_dump); i++)
  		max8998_read_reg(i2c, max8998_dump[i].addr,
  				&max8998_dump[i].val);
  
  	return 0;
  }
  
  /* Restore registers after hibernation */
  static int max8998_restore(struct device *dev)
  {
1b5420e1f   Geliang Tang   mfd: Use to_i2c_c...
309
  	struct i2c_client *i2c = to_i2c_client(dev);
cdd137c9c   MyungJoo Ham   mfd: MAX8998/LP39...
310
311
312
313
314
315
316
317
  	int i;
  
  	for (i = 0; i < ARRAY_SIZE(max8998_dump); i++)
  		max8998_write_reg(i2c, max8998_dump[i].addr,
  				max8998_dump[i].val);
  
  	return 0;
  }
44be0a40d   Mark Brown   mfd: Staticise no...
318
  static const struct dev_pm_ops max8998_pm = {
cdd137c9c   MyungJoo Ham   mfd: MAX8998/LP39...
319
320
321
322
323
  	.suspend = max8998_suspend,
  	.resume = max8998_resume,
  	.freeze = max8998_freeze,
  	.restore = max8998_restore,
  };
156f25285   Kyungmin Park   drivers: regulato...
324
325
326
  static struct i2c_driver max8998_i2c_driver = {
  	.driver = {
  		   .name = "max8998",
cdd137c9c   MyungJoo Ham   mfd: MAX8998/LP39...
327
  		   .pm = &max8998_pm,
b9e38338e   Paul Gortmaker   mfd: max8998: Mak...
328
  		   .suppress_bind_attrs = true,
ee999fb3f   Tomasz Figa   mfd: max8998: Add...
329
  		   .of_match_table = of_match_ptr(max8998_dt_match),
156f25285   Kyungmin Park   drivers: regulato...
330
331
  	},
  	.probe = max8998_i2c_probe,
156f25285   Kyungmin Park   drivers: regulato...
332
333
334
335
336
337
338
339
340
  	.id_table = max8998_i2c_id,
  };
  
  static int __init max8998_i2c_init(void)
  {
  	return i2c_add_driver(&max8998_i2c_driver);
  }
  /* init early so consumer devices can complete system boot */
  subsys_initcall(max8998_i2c_init);