PageRenderTime 31ms CodeModel.GetById 17ms app.highlight 11ms RepoModel.GetById 0ms app.codeStats 1ms

/drivers/w1/slaves/w1_ds2408.c

https://bitbucket.org/cyanogenmod/android_kernel_asus_tf300t
C | 402 lines | 320 code | 59 blank | 23 comment | 60 complexity | 71ddf0ce79b6e60369a0ac09dac0b835 MD5 | raw file
Possible License(s): LGPL-2.0, AGPL-1.0, GPL-2.0
  1/*
  2 *	w1_ds2408.c - w1 family 29 (DS2408) driver
  3 *
  4 * Copyright (c) 2010 Jean-Francois Dagenais <dagenaisj@sonatest.com>
  5 *
  6 * This source code is licensed under the GNU General Public License,
  7 * Version 2. See the file COPYING for more details.
  8 */
  9
 10#include <linux/kernel.h>
 11#include <linux/module.h>
 12#include <linux/moduleparam.h>
 13#include <linux/device.h>
 14#include <linux/types.h>
 15#include <linux/delay.h>
 16#include <linux/slab.h>
 17
 18#include "../w1.h"
 19#include "../w1_int.h"
 20#include "../w1_family.h"
 21
 22MODULE_LICENSE("GPL");
 23MODULE_AUTHOR("Jean-Francois Dagenais <dagenaisj@sonatest.com>");
 24MODULE_DESCRIPTION("w1 family 29 driver for DS2408 8 Pin IO");
 25
 26
 27#define W1_F29_RETRIES		3
 28
 29#define W1_F29_REG_LOGIG_STATE             0x88 /* R */
 30#define W1_F29_REG_OUTPUT_LATCH_STATE      0x89 /* R */
 31#define W1_F29_REG_ACTIVITY_LATCH_STATE    0x8A /* R */
 32#define W1_F29_REG_COND_SEARCH_SELECT_MASK 0x8B /* RW */
 33#define W1_F29_REG_COND_SEARCH_POL_SELECT  0x8C /* RW */
 34#define W1_F29_REG_CONTROL_AND_STATUS      0x8D /* RW */
 35
 36#define W1_F29_FUNC_READ_PIO_REGS          0xF0
 37#define W1_F29_FUNC_CHANN_ACCESS_READ      0xF5
 38#define W1_F29_FUNC_CHANN_ACCESS_WRITE     0x5A
 39/* also used to write the control/status reg (0x8D): */
 40#define W1_F29_FUNC_WRITE_COND_SEARCH_REG  0xCC
 41#define W1_F29_FUNC_RESET_ACTIVITY_LATCHES 0xC3
 42
 43#define W1_F29_SUCCESS_CONFIRM_BYTE        0xAA
 44
 45static int _read_reg(struct w1_slave *sl, u8 address, unsigned char* buf)
 46{
 47	u8 wrbuf[3];
 48	dev_dbg(&sl->dev,
 49			"Reading with slave: %p, reg addr: %0#4x, buff addr: %p",
 50			sl, (unsigned int)address, buf);
 51
 52	if (!buf)
 53		return -EINVAL;
 54
 55	mutex_lock(&sl->master->mutex);
 56	dev_dbg(&sl->dev, "mutex locked");
 57
 58	if (w1_reset_select_slave(sl)) {
 59		mutex_unlock(&sl->master->mutex);
 60		return -EIO;
 61	}
 62
 63	wrbuf[0] = W1_F29_FUNC_READ_PIO_REGS;
 64	wrbuf[1] = address;
 65	wrbuf[2] = 0;
 66	w1_write_block(sl->master, wrbuf, 3);
 67	*buf = w1_read_8(sl->master);
 68
 69	mutex_unlock(&sl->master->mutex);
 70	dev_dbg(&sl->dev, "mutex unlocked");
 71	return 1;
 72}
 73
 74static ssize_t w1_f29_read_state(
 75	struct file *filp, struct kobject *kobj,
 76	struct bin_attribute *bin_attr,
 77	char *buf, loff_t off, size_t count)
 78{
 79	dev_dbg(&kobj_to_w1_slave(kobj)->dev,
 80		"Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
 81		bin_attr->attr.name, kobj, (unsigned int)off, count, buf);
 82	if (count != 1 || off != 0)
 83		return -EFAULT;
 84	return _read_reg(kobj_to_w1_slave(kobj), W1_F29_REG_LOGIG_STATE, buf);
 85}
 86
 87static ssize_t w1_f29_read_output(
 88	struct file *filp, struct kobject *kobj,
 89	struct bin_attribute *bin_attr,
 90	char *buf, loff_t off, size_t count)
 91{
 92	dev_dbg(&kobj_to_w1_slave(kobj)->dev,
 93		"Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
 94		bin_attr->attr.name, kobj, (unsigned int)off, count, buf);
 95	if (count != 1 || off != 0)
 96		return -EFAULT;
 97	return _read_reg(kobj_to_w1_slave(kobj),
 98					 W1_F29_REG_OUTPUT_LATCH_STATE, buf);
 99}
100
101static ssize_t w1_f29_read_activity(
102	struct file *filp, struct kobject *kobj,
103	struct bin_attribute *bin_attr,
104	char *buf, loff_t off, size_t count)
105{
106	dev_dbg(&kobj_to_w1_slave(kobj)->dev,
107		"Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
108		bin_attr->attr.name, kobj, (unsigned int)off, count, buf);
109	if (count != 1 || off != 0)
110		return -EFAULT;
111	return _read_reg(kobj_to_w1_slave(kobj),
112					 W1_F29_REG_ACTIVITY_LATCH_STATE, buf);
113}
114
115static ssize_t w1_f29_read_cond_search_mask(
116	struct file *filp, struct kobject *kobj,
117	struct bin_attribute *bin_attr,
118	char *buf, loff_t off, size_t count)
119{
120	dev_dbg(&kobj_to_w1_slave(kobj)->dev,
121		"Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
122		bin_attr->attr.name, kobj, (unsigned int)off, count, buf);
123	if (count != 1 || off != 0)
124		return -EFAULT;
125	return _read_reg(kobj_to_w1_slave(kobj),
126		W1_F29_REG_COND_SEARCH_SELECT_MASK, buf);
127}
128
129static ssize_t w1_f29_read_cond_search_polarity(
130	struct file *filp, struct kobject *kobj,
131	struct bin_attribute *bin_attr,
132	char *buf, loff_t off, size_t count)
133{
134	if (count != 1 || off != 0)
135		return -EFAULT;
136	return _read_reg(kobj_to_w1_slave(kobj),
137		W1_F29_REG_COND_SEARCH_POL_SELECT, buf);
138}
139
140static ssize_t w1_f29_read_status_control(
141	struct file *filp, struct kobject *kobj,
142	struct bin_attribute *bin_attr,
143	char *buf, loff_t off, size_t count)
144{
145	if (count != 1 || off != 0)
146		return -EFAULT;
147	return _read_reg(kobj_to_w1_slave(kobj),
148		W1_F29_REG_CONTROL_AND_STATUS, buf);
149}
150
151
152
153
154static ssize_t w1_f29_write_output(
155	struct file *filp, struct kobject *kobj,
156	struct bin_attribute *bin_attr,
157	char *buf, loff_t off, size_t count)
158{
159	struct w1_slave *sl = kobj_to_w1_slave(kobj);
160	u8 w1_buf[3];
161	u8 readBack;
162	unsigned int retries = W1_F29_RETRIES;
163
164	if (count != 1 || off != 0)
165		return -EFAULT;
166
167	dev_dbg(&sl->dev, "locking mutex for write_output");
168	mutex_lock(&sl->master->mutex);
169	dev_dbg(&sl->dev, "mutex locked");
170
171	if (w1_reset_select_slave(sl))
172		goto error;
173
174	while (retries--) {
175		w1_buf[0] = W1_F29_FUNC_CHANN_ACCESS_WRITE;
176		w1_buf[1] = *buf;
177		w1_buf[2] = ~(*buf);
178		w1_write_block(sl->master, w1_buf, 3);
179
180		readBack = w1_read_8(sl->master);
181		/* here the master could read another byte which
182		   would be the PIO reg (the actual pin logic state)
183		   since in this driver we don't know which pins are
184		   in and outs, there's no value to read the state and
185		   compare. with (*buf) so end this command abruptly: */
186		if (w1_reset_resume_command(sl->master))
187			goto error;
188
189		if (readBack != 0xAA) {
190			/* try again, the slave is ready for a command */
191			continue;
192		}
193
194		/* go read back the output latches */
195		/* (the direct effect of the write above) */
196		w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS;
197		w1_buf[1] = W1_F29_REG_OUTPUT_LATCH_STATE;
198		w1_buf[2] = 0;
199		w1_write_block(sl->master, w1_buf, 3);
200		/* read the result of the READ_PIO_REGS command */
201		if (w1_read_8(sl->master) == *buf) {
202			/* success! */
203			mutex_unlock(&sl->master->mutex);
204			dev_dbg(&sl->dev,
205				"mutex unlocked, retries:%d", retries);
206			return 1;
207		}
208	}
209error:
210	mutex_unlock(&sl->master->mutex);
211	dev_dbg(&sl->dev, "mutex unlocked in error, retries:%d", retries);
212
213	return -EIO;
214}
215
216
217/**
218 * Writing to the activity file resets the activity latches.
219 */
220static ssize_t w1_f29_write_activity(
221	struct file *filp, struct kobject *kobj,
222	struct bin_attribute *bin_attr,
223	char *buf, loff_t off, size_t count)
224{
225	struct w1_slave *sl = kobj_to_w1_slave(kobj);
226	unsigned int retries = W1_F29_RETRIES;
227
228	if (count != 1 || off != 0)
229		return -EFAULT;
230
231	mutex_lock(&sl->master->mutex);
232
233	if (w1_reset_select_slave(sl))
234		goto error;
235
236	while (retries--) {
237		w1_write_8(sl->master, W1_F29_FUNC_RESET_ACTIVITY_LATCHES);
238		if (w1_read_8(sl->master) == W1_F29_SUCCESS_CONFIRM_BYTE) {
239			mutex_unlock(&sl->master->mutex);
240			return 1;
241		}
242		if (w1_reset_resume_command(sl->master))
243			goto error;
244	}
245
246error:
247	mutex_unlock(&sl->master->mutex);
248	return -EIO;
249}
250
251static ssize_t w1_f29_write_status_control(
252	struct file *filp,
253	struct kobject *kobj,
254	struct bin_attribute *bin_attr,
255	char *buf,
256	loff_t off,
257	size_t count)
258{
259	struct w1_slave *sl = kobj_to_w1_slave(kobj);
260	u8 w1_buf[4];
261	unsigned int retries = W1_F29_RETRIES;
262
263	if (count != 1 || off != 0)
264		return -EFAULT;
265
266	mutex_lock(&sl->master->mutex);
267
268	if (w1_reset_select_slave(sl))
269		goto error;
270
271	while (retries--) {
272		w1_buf[0] = W1_F29_FUNC_WRITE_COND_SEARCH_REG;
273		w1_buf[1] = W1_F29_REG_CONTROL_AND_STATUS;
274		w1_buf[2] = 0;
275		w1_buf[3] = *buf;
276
277		w1_write_block(sl->master, w1_buf, 4);
278		if (w1_reset_resume_command(sl->master))
279			goto error;
280
281		w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS;
282		w1_buf[1] = W1_F29_REG_CONTROL_AND_STATUS;
283		w1_buf[2] = 0;
284
285		w1_write_block(sl->master, w1_buf, 3);
286		if (w1_read_8(sl->master) == *buf) {
287			/* success! */
288			mutex_unlock(&sl->master->mutex);
289			return 1;
290		}
291	}
292error:
293	mutex_unlock(&sl->master->mutex);
294
295	return -EIO;
296}
297
298
299
300#define NB_SYSFS_BIN_FILES 6
301static struct bin_attribute w1_f29_sysfs_bin_files[NB_SYSFS_BIN_FILES] = {
302	{
303		.attr =	{
304			.name = "state",
305			.mode = S_IRUGO,
306		},
307		.size = 1,
308		.read = w1_f29_read_state,
309	},
310	{
311		.attr =	{
312			.name = "output",
313			.mode = S_IRUGO | S_IWUSR | S_IWGRP,
314		},
315		.size = 1,
316		.read = w1_f29_read_output,
317		.write = w1_f29_write_output,
318	},
319	{
320		.attr =	{
321			.name = "activity",
322			.mode = S_IRUGO,
323		},
324		.size = 1,
325		.read = w1_f29_read_activity,
326		.write = w1_f29_write_activity,
327	},
328	{
329		.attr =	{
330			.name = "cond_search_mask",
331			.mode = S_IRUGO,
332		},
333		.size = 1,
334		.read = w1_f29_read_cond_search_mask,
335		.write = 0,
336	},
337	{
338		.attr =	{
339			.name = "cond_search_polarity",
340			.mode = S_IRUGO,
341		},
342		.size = 1,
343		.read = w1_f29_read_cond_search_polarity,
344		.write = 0,
345	},
346	{
347		.attr =	{
348			.name = "status_control",
349			.mode = S_IRUGO | S_IWUSR | S_IWGRP,
350		},
351		.size = 1,
352		.read = w1_f29_read_status_control,
353		.write = w1_f29_write_status_control,
354	}
355};
356
357static int w1_f29_add_slave(struct w1_slave *sl)
358{
359	int err = 0;
360	int i;
361
362	for (i = 0; i < NB_SYSFS_BIN_FILES && !err; ++i)
363		err = sysfs_create_bin_file(
364			&sl->dev.kobj,
365			&(w1_f29_sysfs_bin_files[i]));
366	if (err)
367		while (--i >= 0)
368			sysfs_remove_bin_file(&sl->dev.kobj,
369				&(w1_f29_sysfs_bin_files[i]));
370	return err;
371}
372
373static void w1_f29_remove_slave(struct w1_slave *sl)
374{
375	int i;
376	for (i = NB_SYSFS_BIN_FILES - 1; i >= 0; --i)
377		sysfs_remove_bin_file(&sl->dev.kobj,
378			&(w1_f29_sysfs_bin_files[i]));
379}
380
381static struct w1_family_ops w1_f29_fops = {
382	.add_slave      = w1_f29_add_slave,
383	.remove_slave   = w1_f29_remove_slave,
384};
385
386static struct w1_family w1_family_29 = {
387	.fid = W1_FAMILY_DS2408,
388	.fops = &w1_f29_fops,
389};
390
391static int __init w1_f29_init(void)
392{
393	return w1_register_family(&w1_family_29);
394}
395
396static void __exit w1_f29_exit(void)
397{
398	w1_unregister_family(&w1_family_29);
399}
400
401module_init(w1_f29_init);
402module_exit(w1_f29_exit);