1 // SPDX-License-Identifier: GPL-2.0-only
3 * w1_ds2406.c - w1 family 12 (DS2406) driver
4 * based on w1_ds2413.c by Mariusz Bialonczyk <manio@skyboo.net>
6 * Copyright (c) 2014 Scott Alfter <scott@alfter.us>
9 #include <linux/kernel.h>
10 #include <linux/module.h>
11 #include <linux/moduleparam.h>
12 #include <linux/device.h>
13 #include <linux/types.h>
14 #include <linux/delay.h>
15 #include <linux/slab.h>
16 #include <linux/crc16.h>
20 #define W1_FAMILY_DS2406 0x12
22 #define W1_F12_FUNC_READ_STATUS 0xAA
23 #define W1_F12_FUNC_WRITE_STATUS 0x55
25 static ssize_t
w1_f12_read_state(
26 struct file
*filp
, struct kobject
*kobj
,
27 struct bin_attribute
*bin_attr
,
28 char *buf
, loff_t off
, size_t count
)
30 u8 w1_buf
[6]={W1_F12_FUNC_READ_STATUS
, 7, 0, 0, 0, 0};
31 struct w1_slave
*sl
= kobj_to_w1_slave(kobj
);
41 mutex_lock(&sl
->master
->bus_mutex
);
43 if (w1_reset_select_slave(sl
)) {
44 mutex_unlock(&sl
->master
->bus_mutex
);
48 w1_write_block(sl
->master
, w1_buf
, 3);
49 w1_read_block(sl
->master
, w1_buf
+3, 3);
51 crc
=crc16_byte(crc
, w1_buf
[i
]);
52 if (crc
==0xb001) /* good read? */
53 *buf
=((w1_buf
[3]>>5)&3)|0x30;
57 mutex_unlock(&sl
->master
->bus_mutex
);
62 static ssize_t
w1_f12_write_output(
63 struct file
*filp
, struct kobject
*kobj
,
64 struct bin_attribute
*bin_attr
,
65 char *buf
, loff_t off
, size_t count
)
67 struct w1_slave
*sl
= kobj_to_w1_slave(kobj
);
68 u8 w1_buf
[6]={W1_F12_FUNC_WRITE_STATUS
, 7, 0, 0, 0, 0};
73 if (count
!= 1 || off
!= 0)
76 mutex_lock(&sl
->master
->bus_mutex
);
78 if (w1_reset_select_slave(sl
)) {
79 mutex_unlock(&sl
->master
->bus_mutex
);
83 w1_buf
[3] = (((*buf
)&3)<<5)|0x1F;
84 w1_write_block(sl
->master
, w1_buf
, 4);
85 w1_read_block(sl
->master
, w1_buf
+4, 2);
87 crc
=crc16_byte(crc
, w1_buf
[i
]);
88 if (crc
==0xb001) /* good read? */
89 w1_write_8(sl
->master
, 0xFF);
93 mutex_unlock(&sl
->master
->bus_mutex
);
97 #define NB_SYSFS_BIN_FILES 2
98 static struct bin_attribute w1_f12_sysfs_bin_files
[NB_SYSFS_BIN_FILES
] = {
105 .read
= w1_f12_read_state
,
110 .mode
= S_IRUGO
| S_IWUSR
| S_IWGRP
,
113 .write
= w1_f12_write_output
,
117 static int w1_f12_add_slave(struct w1_slave
*sl
)
122 for (i
= 0; i
< NB_SYSFS_BIN_FILES
&& !err
; ++i
)
123 err
= sysfs_create_bin_file(
125 &(w1_f12_sysfs_bin_files
[i
]));
128 sysfs_remove_bin_file(&sl
->dev
.kobj
,
129 &(w1_f12_sysfs_bin_files
[i
]));
133 static void w1_f12_remove_slave(struct w1_slave
*sl
)
136 for (i
= NB_SYSFS_BIN_FILES
- 1; i
>= 0; --i
)
137 sysfs_remove_bin_file(&sl
->dev
.kobj
,
138 &(w1_f12_sysfs_bin_files
[i
]));
141 static const struct w1_family_ops w1_f12_fops
= {
142 .add_slave
= w1_f12_add_slave
,
143 .remove_slave
= w1_f12_remove_slave
,
146 static struct w1_family w1_family_12
= {
147 .fid
= W1_FAMILY_DS2406
,
148 .fops
= &w1_f12_fops
,
150 module_w1_family(w1_family_12
);
152 MODULE_AUTHOR("Scott Alfter <scott@alfter.us>");
153 MODULE_DESCRIPTION("w1 family 12 driver for DS2406 2 Pin IO");
154 MODULE_LICENSE("GPL");