cregit-Linux how code gets into the kernel

Release 4.11 drivers/w1/slaves/w1_ds2408.c

/*
 *      w1_ds2408.c - w1 family 29 (DS2408) driver
 *
 * Copyright (c) 2010 Jean-Francois Dagenais <dagenaisj@sonatest.com>
 *
 * This source code is licensed under the GNU General Public License,
 * Version 2. See the file COPYING for more details.
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/device.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/slab.h>

#include "../w1.h"
#include "../w1_int.h"
#include "../w1_family.h"

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jean-Francois Dagenais <dagenaisj@sonatest.com>");
MODULE_DESCRIPTION("w1 family 29 driver for DS2408 8 Pin IO");
MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_DS2408));



#define W1_F29_RETRIES		3


#define W1_F29_REG_LOGIG_STATE             0x88 
/* R */

#define W1_F29_REG_OUTPUT_LATCH_STATE      0x89 
/* R */

#define W1_F29_REG_ACTIVITY_LATCH_STATE    0x8A 
/* R */

#define W1_F29_REG_COND_SEARCH_SELECT_MASK 0x8B 
/* RW */

#define W1_F29_REG_COND_SEARCH_POL_SELECT  0x8C 
/* RW */

#define W1_F29_REG_CONTROL_AND_STATUS      0x8D 
/* RW */


#define W1_F29_FUNC_READ_PIO_REGS          0xF0

#define W1_F29_FUNC_CHANN_ACCESS_READ      0xF5

#define W1_F29_FUNC_CHANN_ACCESS_WRITE     0x5A
/* also used to write the control/status reg (0x8D): */

#define W1_F29_FUNC_WRITE_COND_SEARCH_REG  0xCC

#define W1_F29_FUNC_RESET_ACTIVITY_LATCHES 0xC3


#define W1_F29_SUCCESS_CONFIRM_BYTE        0xAA


static int _read_reg(struct w1_slave *sl, u8 address, unsigned char* buf) { u8 wrbuf[3]; dev_dbg(&sl->dev, "Reading with slave: %p, reg addr: %0#4x, buff addr: %p", sl, (unsigned int)address, buf); if (!buf) return -EINVAL; mutex_lock(&sl->master->bus_mutex); dev_dbg(&sl->dev, "mutex locked"); if (w1_reset_select_slave(sl)) { mutex_unlock(&sl->master->bus_mutex); return -EIO; } wrbuf[0] = W1_F29_FUNC_READ_PIO_REGS; wrbuf[1] = address; wrbuf[2] = 0; w1_write_block(sl->master, wrbuf, 3); *buf = w1_read_8(sl->master); mutex_unlock(&sl->master->bus_mutex); dev_dbg(&sl->dev, "mutex unlocked"); return 1; }

Contributors

PersonTokensPropCommitsCommitProp
Jean-François Dagenais15998.15%150.00%
Neil Brown31.85%150.00%
Total162100.00%2100.00%


static ssize_t state_read(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { dev_dbg(&kobj_to_w1_slave(kobj)->dev, "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p", bin_attr->attr.name, kobj, (unsigned int)off, count, buf); if (count != 1 || off != 0) return -EFAULT; return _read_reg(kobj_to_w1_slave(kobj), W1_F29_REG_LOGIG_STATE, buf); }

Contributors

PersonTokensPropCommitsCommitProp
Jean-François Dagenais8898.88%150.00%
Greg Kroah-Hartman11.12%150.00%
Total89100.00%2100.00%


static ssize_t output_read(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { dev_dbg(&kobj_to_w1_slave(kobj)->dev, "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p", bin_attr->attr.name, kobj, (unsigned int)off, count, buf); if (count != 1 || off != 0) return -EFAULT; return _read_reg(kobj_to_w1_slave(kobj), W1_F29_REG_OUTPUT_LATCH_STATE, buf); }

Contributors

PersonTokensPropCommitsCommitProp
Jean-François Dagenais8898.88%150.00%
Greg Kroah-Hartman11.12%150.00%
Total89100.00%2100.00%


static ssize_t activity_read(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { dev_dbg(&kobj_to_w1_slave(kobj)->dev, "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p", bin_attr->attr.name, kobj, (unsigned int)off, count, buf); if (count != 1 || off != 0) return -EFAULT; return _read_reg(kobj_to_w1_slave(kobj), W1_F29_REG_ACTIVITY_LATCH_STATE, buf); }

Contributors

PersonTokensPropCommitsCommitProp
Jean-François Dagenais8898.88%150.00%
Greg Kroah-Hartman11.12%150.00%
Total89100.00%2100.00%


static ssize_t cond_search_mask_read(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { dev_dbg(&kobj_to_w1_slave(kobj)->dev, "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p", bin_attr->attr.name, kobj, (unsigned int)off, count, buf); if (count != 1 || off != 0) return -EFAULT; return _read_reg(kobj_to_w1_slave(kobj), W1_F29_REG_COND_SEARCH_SELECT_MASK, buf); }

Contributors

PersonTokensPropCommitsCommitProp
Jean-François Dagenais8898.88%150.00%
Greg Kroah-Hartman11.12%150.00%
Total89100.00%2100.00%


static ssize_t cond_search_polarity_read(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { if (count != 1 || off != 0) return -EFAULT; return _read_reg(kobj_to_w1_slave(kobj), W1_F29_REG_COND_SEARCH_POL_SELECT, buf); }

Contributors

PersonTokensPropCommitsCommitProp
Jean-François Dagenais5798.28%150.00%
Greg Kroah-Hartman11.72%150.00%
Total58100.00%2100.00%


static ssize_t status_control_read(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { if (count != 1 || off != 0) return -EFAULT; return _read_reg(kobj_to_w1_slave(kobj), W1_F29_REG_CONTROL_AND_STATUS, buf); }

Contributors

PersonTokensPropCommitsCommitProp
Jean-François Dagenais5798.28%150.00%
Greg Kroah-Hartman11.72%150.00%
Total58100.00%2100.00%


static ssize_t output_write(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { struct w1_slave *sl = kobj_to_w1_slave(kobj); u8 w1_buf[3]; u8 readBack; unsigned int retries = W1_F29_RETRIES; if (count != 1 || off != 0) return -EFAULT; dev_dbg(&sl->dev, "locking mutex for write_output"); mutex_lock(&sl->master->bus_mutex); dev_dbg(&sl->dev, "mutex locked"); if (w1_reset_select_slave(sl)) goto error; while (retries--) { w1_buf[0] = W1_F29_FUNC_CHANN_ACCESS_WRITE; w1_buf[1] = *buf; w1_buf[2] = ~(*buf); w1_write_block(sl->master, w1_buf, 3); readBack = w1_read_8(sl->master); if (readBack != W1_F29_SUCCESS_CONFIRM_BYTE) { if (w1_reset_resume_command(sl->master)) goto error; /* try again, the slave is ready for a command */ continue; } #ifdef CONFIG_W1_SLAVE_DS2408_READBACK /* here the master could read another byte which would be the PIO reg (the actual pin logic state) since in this driver we don't know which pins are in and outs, there's no value to read the state and compare. with (*buf) so end this command abruptly: */ if (w1_reset_resume_command(sl->master)) goto error; /* go read back the output latches */ /* (the direct effect of the write above) */ w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS; w1_buf[1] = W1_F29_REG_OUTPUT_LATCH_STATE; w1_buf[2] = 0; w1_write_block(sl->master, w1_buf, 3); /* read the result of the READ_PIO_REGS command */ if (w1_read_8(sl->master) == *buf) #endif { /* success! */ mutex_unlock(&sl->master->bus_mutex); dev_dbg(&sl->dev, "mutex unlocked, retries:%d", retries); return 1; } } error: mutex_unlock(&sl->master->bus_mutex); dev_dbg(&sl->dev, "mutex unlocked in error, retries:%d", retries); return -EIO; }

Contributors

PersonTokensPropCommitsCommitProp
Jean-François Dagenais30298.69%250.00%
Neil Brown30.98%125.00%
Greg Kroah-Hartman10.33%125.00%
Total306100.00%4100.00%

/** * Writing to the activity file resets the activity latches. */
static ssize_t activity_write(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { struct w1_slave *sl = kobj_to_w1_slave(kobj); unsigned int retries = W1_F29_RETRIES; if (count != 1 || off != 0) return -EFAULT; mutex_lock(&sl->master->bus_mutex); if (w1_reset_select_slave(sl)) goto error; while (retries--) { w1_write_8(sl->master, W1_F29_FUNC_RESET_ACTIVITY_LATCHES); if (w1_read_8(sl->master) == W1_F29_SUCCESS_CONFIRM_BYTE) { mutex_unlock(&sl->master->bus_mutex); return 1; } if (w1_reset_resume_command(sl->master)) goto error; } error: mutex_unlock(&sl->master->bus_mutex); return -EIO; }

Contributors

PersonTokensPropCommitsCommitProp
Jean-François Dagenais14797.35%133.33%
Neil Brown31.99%133.33%
Greg Kroah-Hartman10.66%133.33%
Total151100.00%3100.00%


static ssize_t status_control_write(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { struct w1_slave *sl = kobj_to_w1_slave(kobj); u8 w1_buf[4]; unsigned int retries = W1_F29_RETRIES; if (count != 1 || off != 0) return -EFAULT; mutex_lock(&sl->master->bus_mutex); if (w1_reset_select_slave(sl)) goto error; while (retries--) { w1_buf[0] = W1_F29_FUNC_WRITE_COND_SEARCH_REG; w1_buf[1] = W1_F29_REG_CONTROL_AND_STATUS; w1_buf[2] = 0; w1_buf[3] = *buf; w1_write_block(sl->master, w1_buf, 4); if (w1_reset_resume_command(sl->master)) goto error; w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS; w1_buf[1] = W1_F29_REG_CONTROL_AND_STATUS; w1_buf[2] = 0; w1_write_block(sl->master, w1_buf, 3); if (w1_read_8(sl->master) == *buf) { /* success! */ mutex_unlock(&sl->master->bus_mutex); return 1; } } error: mutex_unlock(&sl->master->bus_mutex); return -EIO; }

Contributors

PersonTokensPropCommitsCommitProp
Jean-François Dagenais21898.20%133.33%
Neil Brown31.35%133.33%
Greg Kroah-Hartman10.45%133.33%
Total222100.00%3100.00%

/* * This is a special sequence we must do to ensure the P0 output is not stuck * in test mode. This is described in rev 2 of the ds2408's datasheet * (http://datasheets.maximintegrated.com/en/ds/DS2408.pdf) under * "APPLICATION INFORMATION/Power-up timing". */
static int w1_f29_disable_test_mode(struct w1_slave *sl) { int res; u8 magic[10] = {0x96, }; u64 rn = le64_to_cpu(*((u64*)&sl->reg_num)); memcpy(&magic[1], &rn, 8); magic[9] = 0x3C; mutex_lock(&sl->master->bus_mutex); res = w1_reset_bus(sl->master); if (res) goto out; w1_write_block(sl->master, magic, ARRAY_SIZE(magic)); res = w1_reset_bus(sl->master); out: mutex_unlock(&sl->master->bus_mutex); return res; }

Contributors

PersonTokensPropCommitsCommitProp
Jean-François Dagenais127100.00%1100.00%
Total127100.00%1100.00%

static BIN_ATTR_RO(state, 1); static BIN_ATTR_RW(output, 1); static BIN_ATTR_RW(activity, 1); static BIN_ATTR_RO(cond_search_mask, 1); static BIN_ATTR_RO(cond_search_polarity, 1); static BIN_ATTR_RW(status_control, 1); static struct bin_attribute *w1_f29_bin_attrs[] = { &bin_attr_state, &bin_attr_output, &bin_attr_activity, &bin_attr_cond_search_mask, &bin_attr_cond_search_polarity, &bin_attr_status_control, NULL, }; static const struct attribute_group w1_f29_group = { .bin_attrs = w1_f29_bin_attrs, }; static const struct attribute_group *w1_f29_groups[] = { &w1_f29_group, NULL, }; static struct w1_family_ops w1_f29_fops = { .add_slave = w1_f29_disable_test_mode, .groups = w1_f29_groups, }; static struct w1_family w1_family_29 = { .fid = W1_FAMILY_DS2408, .fops = &w1_f29_fops, }; module_w1_family(w1_family_29);

Overall Contributors

PersonTokensPropCommitsCommitProp
Jean-François Dagenais158593.18%450.00%
Greg Kroah-Hartman935.47%112.50%
Neil Brown120.71%112.50%
Alexander Stein90.53%112.50%
Andrew F. Davis20.12%112.50%
Total1701100.00%8100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.