linux/drivers/w1/slaves/w1_ds2406.c
Andrew F. Davis de0d6dbdbd w1: Add subsystem kernel public interface
Like other subsystems we should be able to define slave devices outside
of the w1 directory. To do this we move public facing interface
definitions to include/linux/w1.h and rename the internal definition
file to w1_internal.h.

As w1_family.h and w1_int.h contained almost entirely public
driver interface definitions we simply removed these files and
moved the remaining definitions into w1_internal.h.

With this we can now start to move slave devices out of w1/slaves and
into the subsystem based on the function they implement, again like
other drivers.

Signed-off-by: Andrew F. Davis <afd@ti.com>
Reviewed-by: Sebastian Reichel <sre@kernel.org>
Acked-by: Evgeniy Polyakov <zbr@ioremap.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2017-06-09 11:54:54 +02:00

157 lines
3.4 KiB
C

/*
* w1_ds2406.c - w1 family 12 (DS2406) driver
* based on w1_ds2413.c by Mariusz Bialonczyk <manio@skyboo.net>
*
* Copyright (c) 2014 Scott Alfter <scott@alfter.us>
*
* 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 <linux/crc16.h>
#include <linux/w1.h>
#define W1_FAMILY_DS2406 0x12
#define W1_F12_FUNC_READ_STATUS 0xAA
#define W1_F12_FUNC_WRITE_STATUS 0x55
static ssize_t w1_f12_read_state(
struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
u8 w1_buf[6]={W1_F12_FUNC_READ_STATUS, 7, 0, 0, 0, 0};
struct w1_slave *sl = kobj_to_w1_slave(kobj);
u16 crc=0;
int i;
ssize_t rtnval=1;
if (off != 0)
return 0;
if (!buf)
return -EINVAL;
mutex_lock(&sl->master->bus_mutex);
if (w1_reset_select_slave(sl)) {
mutex_unlock(&sl->master->bus_mutex);
return -EIO;
}
w1_write_block(sl->master, w1_buf, 3);
w1_read_block(sl->master, w1_buf+3, 3);
for (i=0; i<6; i++)
crc=crc16_byte(crc, w1_buf[i]);
if (crc==0xb001) /* good read? */
*buf=((w1_buf[3]>>5)&3)|0x30;
else
rtnval=-EIO;
mutex_unlock(&sl->master->bus_mutex);
return rtnval;
}
static ssize_t w1_f12_write_output(
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[6]={W1_F12_FUNC_WRITE_STATUS, 7, 0, 0, 0, 0};
u16 crc=0;
int i;
ssize_t rtnval=1;
if (count != 1 || off != 0)
return -EFAULT;
mutex_lock(&sl->master->bus_mutex);
if (w1_reset_select_slave(sl)) {
mutex_unlock(&sl->master->bus_mutex);
return -EIO;
}
w1_buf[3] = (((*buf)&3)<<5)|0x1F;
w1_write_block(sl->master, w1_buf, 4);
w1_read_block(sl->master, w1_buf+4, 2);
for (i=0; i<6; i++)
crc=crc16_byte(crc, w1_buf[i]);
if (crc==0xb001) /* good read? */
w1_write_8(sl->master, 0xFF);
else
rtnval=-EIO;
mutex_unlock(&sl->master->bus_mutex);
return rtnval;
}
#define NB_SYSFS_BIN_FILES 2
static struct bin_attribute w1_f12_sysfs_bin_files[NB_SYSFS_BIN_FILES] = {
{
.attr = {
.name = "state",
.mode = S_IRUGO,
},
.size = 1,
.read = w1_f12_read_state,
},
{
.attr = {
.name = "output",
.mode = S_IRUGO | S_IWUSR | S_IWGRP,
},
.size = 1,
.write = w1_f12_write_output,
}
};
static int w1_f12_add_slave(struct w1_slave *sl)
{
int err = 0;
int i;
for (i = 0; i < NB_SYSFS_BIN_FILES && !err; ++i)
err = sysfs_create_bin_file(
&sl->dev.kobj,
&(w1_f12_sysfs_bin_files[i]));
if (err)
while (--i >= 0)
sysfs_remove_bin_file(&sl->dev.kobj,
&(w1_f12_sysfs_bin_files[i]));
return err;
}
static void w1_f12_remove_slave(struct w1_slave *sl)
{
int i;
for (i = NB_SYSFS_BIN_FILES - 1; i >= 0; --i)
sysfs_remove_bin_file(&sl->dev.kobj,
&(w1_f12_sysfs_bin_files[i]));
}
static struct w1_family_ops w1_f12_fops = {
.add_slave = w1_f12_add_slave,
.remove_slave = w1_f12_remove_slave,
};
static struct w1_family w1_family_12 = {
.fid = W1_FAMILY_DS2406,
.fops = &w1_f12_fops,
};
module_w1_family(w1_family_12);
MODULE_AUTHOR("Scott Alfter <scott@alfter.us>");
MODULE_DESCRIPTION("w1 family 12 driver for DS2406 2 Pin IO");
MODULE_LICENSE("GPL");