Blame view

drivers/mfd/max8998.c 8.38 KB
156f25285   Kyungmin Park   drivers: regulato...
1
  /*
2c7e6f579   Joonyoung Shim   mfd: Add MAX8998 ...
2
   * max8998.c - mfd core driver for the Maxim 8998
156f25285   Kyungmin Park   drivers: regulato...
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
   *
   *  Copyright (C) 2009-2010 Samsung Electronics
   *  Kyungmin Park <kyungmin.park@samsung.com>
   *  Marek Szyprowski <m.szyprowski@samsung.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.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   */
  
  #include <linux/module.h>
  #include <linux/moduleparam.h>
  #include <linux/init.h>
  #include <linux/slab.h>
  #include <linux/i2c.h>
cdd137c9c   MyungJoo Ham   mfd: MAX8998/LP39...
28
29
  #include <linux/interrupt.h>
  #include <linux/pm_runtime.h>
156f25285   Kyungmin Park   drivers: regulato...
30
31
32
33
  #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 ...
34
  #define RTC_I2C_ADDR		(0x0c >> 1)
156f25285   Kyungmin Park   drivers: regulato...
35
36
37
  static struct mfd_cell max8998_devs[] = {
  	{
  		.name = "max8998-pmic",
9b16c0a43   Joonyoung Shim   rtc: Add MAX8998 ...
38
39
  	}, {
  		.name = "max8998-rtc",
bb4ce9708   Donggeun Kim   power_supply: Add...
40
41
  	}, {
  		.name = "max8998-battery",
9b16c0a43   Joonyoung Shim   rtc: Add MAX8998 ...
42
  	},
156f25285   Kyungmin Park   drivers: regulato...
43
  };
337ce5d1c   MyungJoo Ham   mfd: Support LP39...
44
45
46
47
48
49
50
  static struct mfd_cell lp3974_devs[] = {
  	{
  		.name = "lp3974-pmic",
  	}, {
  		.name = "lp3974-rtc",
  	},
  };
676e02d7a   Joonyoung Shim   mfd: Use i2c_clie...
51
  int max8998_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest)
156f25285   Kyungmin Park   drivers: regulato...
52
  {
676e02d7a   Joonyoung Shim   mfd: Use i2c_clie...
53
  	struct max8998_dev *max8998 = i2c_get_clientdata(i2c);
156f25285   Kyungmin Park   drivers: regulato...
54
55
56
  	int ret;
  
  	mutex_lock(&max8998->iolock);
676e02d7a   Joonyoung Shim   mfd: Use i2c_clie...
57
  	ret = i2c_smbus_read_byte_data(i2c, reg);
156f25285   Kyungmin Park   drivers: regulato...
58
59
60
61
62
63
64
65
  	mutex_unlock(&max8998->iolock);
  	if (ret < 0)
  		return ret;
  
  	ret &= 0xff;
  	*dest = ret;
  	return 0;
  }
676e02d7a   Joonyoung Shim   mfd: Use i2c_clie...
66
  EXPORT_SYMBOL(max8998_read_reg);
156f25285   Kyungmin Park   drivers: regulato...
67

2c7e6f579   Joonyoung Shim   mfd: Add MAX8998 ...
68
69
70
71
72
73
74
75
76
77
78
79
80
81
  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...
82
  int max8998_write_reg(struct i2c_client *i2c, u8 reg, u8 value)
156f25285   Kyungmin Park   drivers: regulato...
83
  {
676e02d7a   Joonyoung Shim   mfd: Use i2c_clie...
84
  	struct max8998_dev *max8998 = i2c_get_clientdata(i2c);
156f25285   Kyungmin Park   drivers: regulato...
85
86
87
  	int ret;
  
  	mutex_lock(&max8998->iolock);
676e02d7a   Joonyoung Shim   mfd: Use i2c_clie...
88
  	ret = i2c_smbus_write_byte_data(i2c, reg, value);
156f25285   Kyungmin Park   drivers: regulato...
89
90
91
  	mutex_unlock(&max8998->iolock);
  	return ret;
  }
676e02d7a   Joonyoung Shim   mfd: Use i2c_clie...
92
  EXPORT_SYMBOL(max8998_write_reg);
156f25285   Kyungmin Park   drivers: regulato...
93

9b16c0a43   Joonyoung Shim   rtc: Add MAX8998 ...
94
95
96
97
98
99
100
101
102
103
104
105
106
107
  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...
108
  int max8998_update_reg(struct i2c_client *i2c, u8 reg, u8 val, u8 mask)
156f25285   Kyungmin Park   drivers: regulato...
109
  {
676e02d7a   Joonyoung Shim   mfd: Use i2c_clie...
110
  	struct max8998_dev *max8998 = i2c_get_clientdata(i2c);
156f25285   Kyungmin Park   drivers: regulato...
111
112
113
  	int ret;
  
  	mutex_lock(&max8998->iolock);
676e02d7a   Joonyoung Shim   mfd: Use i2c_clie...
114
  	ret = i2c_smbus_read_byte_data(i2c, reg);
156f25285   Kyungmin Park   drivers: regulato...
115
116
117
  	if (ret >= 0) {
  		u8 old_val = ret & 0xff;
  		u8 new_val = (val & mask) | (old_val & (~mask));
676e02d7a   Joonyoung Shim   mfd: Use i2c_clie...
118
  		ret = i2c_smbus_write_byte_data(i2c, reg, new_val);
156f25285   Kyungmin Park   drivers: regulato...
119
120
121
122
  	}
  	mutex_unlock(&max8998->iolock);
  	return ret;
  }
676e02d7a   Joonyoung Shim   mfd: Use i2c_clie...
123
  EXPORT_SYMBOL(max8998_update_reg);
156f25285   Kyungmin Park   drivers: regulato...
124
125
126
127
  
  static int max8998_i2c_probe(struct i2c_client *i2c,
  			    const struct i2c_device_id *id)
  {
2c7e6f579   Joonyoung Shim   mfd: Add MAX8998 ...
128
  	struct max8998_platform_data *pdata = i2c->dev.platform_data;
156f25285   Kyungmin Park   drivers: regulato...
129
130
131
132
  	struct max8998_dev *max8998;
  	int ret = 0;
  
  	max8998 = kzalloc(sizeof(struct max8998_dev), GFP_KERNEL);
8f1f151ed   Axel Lin   mfd: max8998 - fi...
133
  	if (max8998 == NULL)
156f25285   Kyungmin Park   drivers: regulato...
134
  		return -ENOMEM;
156f25285   Kyungmin Park   drivers: regulato...
135
136
137
  
  	i2c_set_clientdata(i2c, max8998);
  	max8998->dev = &i2c->dev;
676e02d7a   Joonyoung Shim   mfd: Use i2c_clie...
138
  	max8998->i2c = i2c;
2c7e6f579   Joonyoung Shim   mfd: Add MAX8998 ...
139
  	max8998->irq = i2c->irq;
509bd4764   Lukasz Majewski   mfd: Support for ...
140
  	max8998->type = id->driver_data;
2c7e6f579   Joonyoung Shim   mfd: Add MAX8998 ...
141
142
143
  	if (pdata) {
  		max8998->ono = pdata->ono;
  		max8998->irq_base = pdata->irq_base;
cdd137c9c   MyungJoo Ham   mfd: MAX8998/LP39...
144
  		max8998->wakeup = pdata->wakeup;
2c7e6f579   Joonyoung Shim   mfd: Add MAX8998 ...
145
  	}
156f25285   Kyungmin Park   drivers: regulato...
146
  	mutex_init(&max8998->iolock);
9b16c0a43   Joonyoung Shim   rtc: Add MAX8998 ...
147
148
  	max8998->rtc = i2c_new_dummy(i2c->adapter, RTC_I2C_ADDR);
  	i2c_set_clientdata(max8998->rtc, max8998);
2c7e6f579   Joonyoung Shim   mfd: Add MAX8998 ...
149
  	max8998_irq_init(max8998);
cdd137c9c   MyungJoo Ham   mfd: MAX8998/LP39...
150
  	pm_runtime_set_active(max8998->dev);
337ce5d1c   MyungJoo Ham   mfd: Support LP39...
151
152
153
154
155
156
157
158
159
160
161
162
163
164
  	switch (id->driver_data) {
  	case TYPE_LP3974:
  		ret = mfd_add_devices(max8998->dev, -1,
  				lp3974_devs, ARRAY_SIZE(lp3974_devs),
  				NULL, 0);
  		break;
  	case TYPE_MAX8998:
  		ret = mfd_add_devices(max8998->dev, -1,
  				max8998_devs, ARRAY_SIZE(max8998_devs),
  				NULL, 0);
  		break;
  	default:
  		ret = -EINVAL;
  	}
156f25285   Kyungmin Park   drivers: regulato...
165
166
  	if (ret < 0)
  		goto err;
7ef73598d   Jonghwan Choi   mfd: Use standard...
167
  	device_init_wakeup(max8998->dev, max8998->wakeup);
156f25285   Kyungmin Park   drivers: regulato...
168
169
170
171
  	return ret;
  
  err:
  	mfd_remove_devices(max8998->dev);
7484552eb   Axel Lin   mfd: Fix resource...
172
173
  	max8998_irq_exit(max8998);
  	i2c_unregister_device(max8998->rtc);
156f25285   Kyungmin Park   drivers: regulato...
174
175
176
177
178
179
180
181
182
  	kfree(max8998);
  	return ret;
  }
  
  static int max8998_i2c_remove(struct i2c_client *i2c)
  {
  	struct max8998_dev *max8998 = i2c_get_clientdata(i2c);
  
  	mfd_remove_devices(max8998->dev);
7484552eb   Axel Lin   mfd: Fix resource...
183
184
  	max8998_irq_exit(max8998);
  	i2c_unregister_device(max8998->rtc);
156f25285   Kyungmin Park   drivers: regulato...
185
186
187
188
189
190
  	kfree(max8998);
  
  	return 0;
  }
  
  static const struct i2c_device_id max8998_i2c_id[] = {
509bd4764   Lukasz Majewski   mfd: Support for ...
191
192
  	{ "max8998", TYPE_MAX8998 },
  	{ "lp3974", TYPE_LP3974},
f8539ddcb   Kyungmin Park   mfd: LP3974 PMIC ...
193
  	{ }
156f25285   Kyungmin Park   drivers: regulato...
194
195
  };
  MODULE_DEVICE_TABLE(i2c, max8998_i2c_id);
cdd137c9c   MyungJoo Ham   mfd: MAX8998/LP39...
196
197
198
199
  static int max8998_suspend(struct device *dev)
  {
  	struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
  	struct max8998_dev *max8998 = i2c_get_clientdata(i2c);
7ef73598d   Jonghwan Choi   mfd: Use standard...
200
  	if (device_may_wakeup(dev))
d5bb12216   Thomas Gleixner   mfd: Cleanup irq ...
201
  		irq_set_irq_wake(max8998->irq, 1);
cdd137c9c   MyungJoo Ham   mfd: MAX8998/LP39...
202
203
204
205
206
207
208
  	return 0;
  }
  
  static int max8998_resume(struct device *dev)
  {
  	struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
  	struct max8998_dev *max8998 = i2c_get_clientdata(i2c);
7ef73598d   Jonghwan Choi   mfd: Use standard...
209
  	if (device_may_wakeup(dev))
d5bb12216   Thomas Gleixner   mfd: Cleanup irq ...
210
  		irq_set_irq_wake(max8998->irq, 0);
cdd137c9c   MyungJoo Ham   mfd: MAX8998/LP39...
211
212
213
214
215
216
217
218
219
220
221
222
223
  	/*
  	 * 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...
224
  static struct max8998_reg_dump max8998_dump[] = {
cdd137c9c   MyungJoo Ham   mfd: MAX8998/LP39...
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
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
  	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)
  {
  	struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
  	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)
  {
  	struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
  	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...
288
  static const struct dev_pm_ops max8998_pm = {
cdd137c9c   MyungJoo Ham   mfd: MAX8998/LP39...
289
290
291
292
293
  	.suspend = max8998_suspend,
  	.resume = max8998_resume,
  	.freeze = max8998_freeze,
  	.restore = max8998_restore,
  };
156f25285   Kyungmin Park   drivers: regulato...
294
295
296
297
  static struct i2c_driver max8998_i2c_driver = {
  	.driver = {
  		   .name = "max8998",
  		   .owner = THIS_MODULE,
cdd137c9c   MyungJoo Ham   mfd: MAX8998/LP39...
298
  		   .pm = &max8998_pm,
156f25285   Kyungmin Park   drivers: regulato...
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
  	},
  	.probe = max8998_i2c_probe,
  	.remove = max8998_i2c_remove,
  	.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);
  
  static void __exit max8998_i2c_exit(void)
  {
  	i2c_del_driver(&max8998_i2c_driver);
  }
  module_exit(max8998_i2c_exit);
  
  MODULE_DESCRIPTION("MAXIM 8998 multi-function core driver");
  MODULE_AUTHOR("Kyungmin Park <kyungmin.park@samsung.com>");
  MODULE_LICENSE("GPL");