Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/base/regmap/regmap-w1.c
26428 views
1
// SPDX-License-Identifier: GPL-2.0
2
//
3
// Register map access API - W1 (1-Wire) support
4
//
5
// Copyright (c) 2017 Radioavionica Corporation
6
// Author: Alex A. Mihaylov <[email protected]>
7
8
#include <linux/regmap.h>
9
#include <linux/module.h>
10
#include <linux/w1.h>
11
12
#include "internal.h"
13
14
#define W1_CMD_READ_DATA 0x69
15
#define W1_CMD_WRITE_DATA 0x6C
16
17
/*
18
* 1-Wire slaves registers with addess 8 bit and data 8 bit
19
*/
20
21
static int w1_reg_a8_v8_read(void *context, unsigned int reg, unsigned int *val)
22
{
23
struct device *dev = context;
24
struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
25
int ret = 0;
26
27
if (reg > 255)
28
return -EINVAL;
29
30
mutex_lock(&sl->master->bus_mutex);
31
if (!w1_reset_select_slave(sl)) {
32
w1_write_8(sl->master, W1_CMD_READ_DATA);
33
w1_write_8(sl->master, reg);
34
*val = w1_read_8(sl->master);
35
} else {
36
ret = -ENODEV;
37
}
38
mutex_unlock(&sl->master->bus_mutex);
39
40
return ret;
41
}
42
43
static int w1_reg_a8_v8_write(void *context, unsigned int reg, unsigned int val)
44
{
45
struct device *dev = context;
46
struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
47
int ret = 0;
48
49
if (reg > 255)
50
return -EINVAL;
51
52
mutex_lock(&sl->master->bus_mutex);
53
if (!w1_reset_select_slave(sl)) {
54
w1_write_8(sl->master, W1_CMD_WRITE_DATA);
55
w1_write_8(sl->master, reg);
56
w1_write_8(sl->master, val);
57
} else {
58
ret = -ENODEV;
59
}
60
mutex_unlock(&sl->master->bus_mutex);
61
62
return ret;
63
}
64
65
/*
66
* 1-Wire slaves registers with addess 8 bit and data 16 bit
67
*/
68
69
static int w1_reg_a8_v16_read(void *context, unsigned int reg,
70
unsigned int *val)
71
{
72
struct device *dev = context;
73
struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
74
int ret = 0;
75
76
if (reg > 255)
77
return -EINVAL;
78
79
mutex_lock(&sl->master->bus_mutex);
80
if (!w1_reset_select_slave(sl)) {
81
w1_write_8(sl->master, W1_CMD_READ_DATA);
82
w1_write_8(sl->master, reg);
83
*val = w1_read_8(sl->master);
84
*val |= w1_read_8(sl->master)<<8;
85
} else {
86
ret = -ENODEV;
87
}
88
mutex_unlock(&sl->master->bus_mutex);
89
90
return ret;
91
}
92
93
static int w1_reg_a8_v16_write(void *context, unsigned int reg,
94
unsigned int val)
95
{
96
struct device *dev = context;
97
struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
98
int ret = 0;
99
100
if (reg > 255)
101
return -EINVAL;
102
103
mutex_lock(&sl->master->bus_mutex);
104
if (!w1_reset_select_slave(sl)) {
105
w1_write_8(sl->master, W1_CMD_WRITE_DATA);
106
w1_write_8(sl->master, reg);
107
w1_write_8(sl->master, val & 0x00FF);
108
w1_write_8(sl->master, val>>8 & 0x00FF);
109
} else {
110
ret = -ENODEV;
111
}
112
mutex_unlock(&sl->master->bus_mutex);
113
114
return ret;
115
}
116
117
/*
118
* 1-Wire slaves registers with addess 16 bit and data 16 bit
119
*/
120
121
static int w1_reg_a16_v16_read(void *context, unsigned int reg,
122
unsigned int *val)
123
{
124
struct device *dev = context;
125
struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
126
int ret = 0;
127
128
if (reg > 65535)
129
return -EINVAL;
130
131
mutex_lock(&sl->master->bus_mutex);
132
if (!w1_reset_select_slave(sl)) {
133
w1_write_8(sl->master, W1_CMD_READ_DATA);
134
w1_write_8(sl->master, reg & 0x00FF);
135
w1_write_8(sl->master, reg>>8 & 0x00FF);
136
*val = w1_read_8(sl->master);
137
*val |= w1_read_8(sl->master)<<8;
138
} else {
139
ret = -ENODEV;
140
}
141
mutex_unlock(&sl->master->bus_mutex);
142
143
return ret;
144
}
145
146
static int w1_reg_a16_v16_write(void *context, unsigned int reg,
147
unsigned int val)
148
{
149
struct device *dev = context;
150
struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
151
int ret = 0;
152
153
if (reg > 65535)
154
return -EINVAL;
155
156
mutex_lock(&sl->master->bus_mutex);
157
if (!w1_reset_select_slave(sl)) {
158
w1_write_8(sl->master, W1_CMD_WRITE_DATA);
159
w1_write_8(sl->master, reg & 0x00FF);
160
w1_write_8(sl->master, reg>>8 & 0x00FF);
161
w1_write_8(sl->master, val & 0x00FF);
162
w1_write_8(sl->master, val>>8 & 0x00FF);
163
} else {
164
ret = -ENODEV;
165
}
166
mutex_unlock(&sl->master->bus_mutex);
167
168
return ret;
169
}
170
171
/*
172
* Various types of supported bus addressing
173
*/
174
175
static const struct regmap_bus regmap_w1_bus_a8_v8 = {
176
.reg_read = w1_reg_a8_v8_read,
177
.reg_write = w1_reg_a8_v8_write,
178
};
179
180
static const struct regmap_bus regmap_w1_bus_a8_v16 = {
181
.reg_read = w1_reg_a8_v16_read,
182
.reg_write = w1_reg_a8_v16_write,
183
};
184
185
static const struct regmap_bus regmap_w1_bus_a16_v16 = {
186
.reg_read = w1_reg_a16_v16_read,
187
.reg_write = w1_reg_a16_v16_write,
188
};
189
190
static const struct regmap_bus *regmap_get_w1_bus(struct device *w1_dev,
191
const struct regmap_config *config)
192
{
193
if (config->reg_bits == 8 && config->val_bits == 8)
194
return &regmap_w1_bus_a8_v8;
195
196
if (config->reg_bits == 8 && config->val_bits == 16)
197
return &regmap_w1_bus_a8_v16;
198
199
if (config->reg_bits == 16 && config->val_bits == 16)
200
return &regmap_w1_bus_a16_v16;
201
202
return ERR_PTR(-ENOTSUPP);
203
}
204
205
struct regmap *__regmap_init_w1(struct device *w1_dev,
206
const struct regmap_config *config,
207
struct lock_class_key *lock_key,
208
const char *lock_name)
209
{
210
211
const struct regmap_bus *bus = regmap_get_w1_bus(w1_dev, config);
212
213
if (IS_ERR(bus))
214
return ERR_CAST(bus);
215
216
return __regmap_init(w1_dev, bus, w1_dev, config,
217
lock_key, lock_name);
218
}
219
EXPORT_SYMBOL_GPL(__regmap_init_w1);
220
221
struct regmap *__devm_regmap_init_w1(struct device *w1_dev,
222
const struct regmap_config *config,
223
struct lock_class_key *lock_key,
224
const char *lock_name)
225
{
226
227
const struct regmap_bus *bus = regmap_get_w1_bus(w1_dev, config);
228
229
if (IS_ERR(bus))
230
return ERR_CAST(bus);
231
232
return __devm_regmap_init(w1_dev, bus, w1_dev, config,
233
lock_key, lock_name);
234
}
235
EXPORT_SYMBOL_GPL(__devm_regmap_init_w1);
236
237
MODULE_DESCRIPTION("Register map access API - W1 (1-Wire) support");
238
MODULE_LICENSE("GPL");
239
240