Linux Audio

Check our new training course

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