Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/mfd/max8925-i2c.c
15112 views
1
/*
2
* I2C driver for Maxim MAX8925
3
*
4
* Copyright (C) 2009 Marvell International Ltd.
5
* Haojian Zhuang <[email protected]>
6
*
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License version 2 as
9
* published by the Free Software Foundation.
10
*/
11
#include <linux/kernel.h>
12
#include <linux/module.h>
13
#include <linux/platform_device.h>
14
#include <linux/i2c.h>
15
#include <linux/mfd/max8925.h>
16
#include <linux/slab.h>
17
18
#define RTC_I2C_ADDR 0x68
19
#define ADC_I2C_ADDR 0x47
20
21
static inline int max8925_read_device(struct i2c_client *i2c,
22
int reg, int bytes, void *dest)
23
{
24
int ret;
25
26
if (bytes > 1)
27
ret = i2c_smbus_read_i2c_block_data(i2c, reg, bytes, dest);
28
else {
29
ret = i2c_smbus_read_byte_data(i2c, reg);
30
if (ret < 0)
31
return ret;
32
*(unsigned char *)dest = (unsigned char)ret;
33
}
34
return ret;
35
}
36
37
static inline int max8925_write_device(struct i2c_client *i2c,
38
int reg, int bytes, void *src)
39
{
40
unsigned char buf[bytes + 1];
41
int ret;
42
43
buf[0] = (unsigned char)reg;
44
memcpy(&buf[1], src, bytes);
45
46
ret = i2c_master_send(i2c, buf, bytes + 1);
47
if (ret < 0)
48
return ret;
49
return 0;
50
}
51
52
int max8925_reg_read(struct i2c_client *i2c, int reg)
53
{
54
struct max8925_chip *chip = i2c_get_clientdata(i2c);
55
unsigned char data = 0;
56
int ret;
57
58
mutex_lock(&chip->io_lock);
59
ret = max8925_read_device(i2c, reg, 1, &data);
60
mutex_unlock(&chip->io_lock);
61
62
if (ret < 0)
63
return ret;
64
else
65
return (int)data;
66
}
67
EXPORT_SYMBOL(max8925_reg_read);
68
69
int max8925_reg_write(struct i2c_client *i2c, int reg,
70
unsigned char data)
71
{
72
struct max8925_chip *chip = i2c_get_clientdata(i2c);
73
int ret;
74
75
mutex_lock(&chip->io_lock);
76
ret = max8925_write_device(i2c, reg, 1, &data);
77
mutex_unlock(&chip->io_lock);
78
79
return ret;
80
}
81
EXPORT_SYMBOL(max8925_reg_write);
82
83
int max8925_bulk_read(struct i2c_client *i2c, int reg,
84
int count, unsigned char *buf)
85
{
86
struct max8925_chip *chip = i2c_get_clientdata(i2c);
87
int ret;
88
89
mutex_lock(&chip->io_lock);
90
ret = max8925_read_device(i2c, reg, count, buf);
91
mutex_unlock(&chip->io_lock);
92
93
return ret;
94
}
95
EXPORT_SYMBOL(max8925_bulk_read);
96
97
int max8925_bulk_write(struct i2c_client *i2c, int reg,
98
int count, unsigned char *buf)
99
{
100
struct max8925_chip *chip = i2c_get_clientdata(i2c);
101
int ret;
102
103
mutex_lock(&chip->io_lock);
104
ret = max8925_write_device(i2c, reg, count, buf);
105
mutex_unlock(&chip->io_lock);
106
107
return ret;
108
}
109
EXPORT_SYMBOL(max8925_bulk_write);
110
111
int max8925_set_bits(struct i2c_client *i2c, int reg,
112
unsigned char mask, unsigned char data)
113
{
114
struct max8925_chip *chip = i2c_get_clientdata(i2c);
115
unsigned char value;
116
int ret;
117
118
mutex_lock(&chip->io_lock);
119
ret = max8925_read_device(i2c, reg, 1, &value);
120
if (ret < 0)
121
goto out;
122
value &= ~mask;
123
value |= data;
124
ret = max8925_write_device(i2c, reg, 1, &value);
125
out:
126
mutex_unlock(&chip->io_lock);
127
return ret;
128
}
129
EXPORT_SYMBOL(max8925_set_bits);
130
131
132
static const struct i2c_device_id max8925_id_table[] = {
133
{ "max8925", 0 },
134
{ },
135
};
136
MODULE_DEVICE_TABLE(i2c, max8925_id_table);
137
138
static int __devinit max8925_probe(struct i2c_client *client,
139
const struct i2c_device_id *id)
140
{
141
struct max8925_platform_data *pdata = client->dev.platform_data;
142
static struct max8925_chip *chip;
143
144
if (!pdata) {
145
pr_info("%s: platform data is missing\n", __func__);
146
return -EINVAL;
147
}
148
149
chip = kzalloc(sizeof(struct max8925_chip), GFP_KERNEL);
150
if (chip == NULL)
151
return -ENOMEM;
152
chip->i2c = client;
153
chip->dev = &client->dev;
154
i2c_set_clientdata(client, chip);
155
dev_set_drvdata(chip->dev, chip);
156
mutex_init(&chip->io_lock);
157
158
chip->rtc = i2c_new_dummy(chip->i2c->adapter, RTC_I2C_ADDR);
159
i2c_set_clientdata(chip->rtc, chip);
160
161
chip->adc = i2c_new_dummy(chip->i2c->adapter, ADC_I2C_ADDR);
162
i2c_set_clientdata(chip->adc, chip);
163
164
max8925_device_init(chip, pdata);
165
166
return 0;
167
}
168
169
static int __devexit max8925_remove(struct i2c_client *client)
170
{
171
struct max8925_chip *chip = i2c_get_clientdata(client);
172
173
max8925_device_exit(chip);
174
i2c_unregister_device(chip->adc);
175
i2c_unregister_device(chip->rtc);
176
kfree(chip);
177
return 0;
178
}
179
180
static struct i2c_driver max8925_driver = {
181
.driver = {
182
.name = "max8925",
183
.owner = THIS_MODULE,
184
},
185
.probe = max8925_probe,
186
.remove = __devexit_p(max8925_remove),
187
.id_table = max8925_id_table,
188
};
189
190
static int __init max8925_i2c_init(void)
191
{
192
int ret;
193
194
ret = i2c_add_driver(&max8925_driver);
195
if (ret != 0)
196
pr_err("Failed to register MAX8925 I2C driver: %d\n", ret);
197
return ret;
198
}
199
subsys_initcall(max8925_i2c_init);
200
201
static void __exit max8925_i2c_exit(void)
202
{
203
i2c_del_driver(&max8925_driver);
204
}
205
module_exit(max8925_i2c_exit);
206
207
MODULE_DESCRIPTION("I2C Driver for Maxim 8925");
208
MODULE_AUTHOR("Haojian Zhuang <[email protected]>");
209
MODULE_LICENSE("GPL");
210
211