18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *	w1_ds2408.c - w1 family 29 (DS2408) driver
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (c) 2010 Jean-Francois Dagenais <dagenaisj@sonatest.com>
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <linux/kernel.h>
98c2ecf20Sopenharmony_ci#include <linux/module.h>
108c2ecf20Sopenharmony_ci#include <linux/moduleparam.h>
118c2ecf20Sopenharmony_ci#include <linux/device.h>
128c2ecf20Sopenharmony_ci#include <linux/types.h>
138c2ecf20Sopenharmony_ci#include <linux/delay.h>
148c2ecf20Sopenharmony_ci#include <linux/slab.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#include <linux/w1.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#define W1_FAMILY_DS2408	0x29
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci#define W1_F29_RETRIES		3
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#define W1_F29_REG_LOGIG_STATE             0x88 /* R */
238c2ecf20Sopenharmony_ci#define W1_F29_REG_OUTPUT_LATCH_STATE      0x89 /* R */
248c2ecf20Sopenharmony_ci#define W1_F29_REG_ACTIVITY_LATCH_STATE    0x8A /* R */
258c2ecf20Sopenharmony_ci#define W1_F29_REG_COND_SEARCH_SELECT_MASK 0x8B /* RW */
268c2ecf20Sopenharmony_ci#define W1_F29_REG_COND_SEARCH_POL_SELECT  0x8C /* RW */
278c2ecf20Sopenharmony_ci#define W1_F29_REG_CONTROL_AND_STATUS      0x8D /* RW */
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci#define W1_F29_FUNC_READ_PIO_REGS          0xF0
308c2ecf20Sopenharmony_ci#define W1_F29_FUNC_CHANN_ACCESS_READ      0xF5
318c2ecf20Sopenharmony_ci#define W1_F29_FUNC_CHANN_ACCESS_WRITE     0x5A
328c2ecf20Sopenharmony_ci/* also used to write the control/status reg (0x8D): */
338c2ecf20Sopenharmony_ci#define W1_F29_FUNC_WRITE_COND_SEARCH_REG  0xCC
348c2ecf20Sopenharmony_ci#define W1_F29_FUNC_RESET_ACTIVITY_LATCHES 0xC3
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci#define W1_F29_SUCCESS_CONFIRM_BYTE        0xAA
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_cistatic int _read_reg(struct w1_slave *sl, u8 address, unsigned char* buf)
398c2ecf20Sopenharmony_ci{
408c2ecf20Sopenharmony_ci	u8 wrbuf[3];
418c2ecf20Sopenharmony_ci	dev_dbg(&sl->dev,
428c2ecf20Sopenharmony_ci			"Reading with slave: %p, reg addr: %0#4x, buff addr: %p",
438c2ecf20Sopenharmony_ci			sl, (unsigned int)address, buf);
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci	if (!buf)
468c2ecf20Sopenharmony_ci		return -EINVAL;
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	mutex_lock(&sl->master->bus_mutex);
498c2ecf20Sopenharmony_ci	dev_dbg(&sl->dev, "mutex locked");
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci	if (w1_reset_select_slave(sl)) {
528c2ecf20Sopenharmony_ci		mutex_unlock(&sl->master->bus_mutex);
538c2ecf20Sopenharmony_ci		return -EIO;
548c2ecf20Sopenharmony_ci	}
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci	wrbuf[0] = W1_F29_FUNC_READ_PIO_REGS;
578c2ecf20Sopenharmony_ci	wrbuf[1] = address;
588c2ecf20Sopenharmony_ci	wrbuf[2] = 0;
598c2ecf20Sopenharmony_ci	w1_write_block(sl->master, wrbuf, 3);
608c2ecf20Sopenharmony_ci	*buf = w1_read_8(sl->master);
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci	mutex_unlock(&sl->master->bus_mutex);
638c2ecf20Sopenharmony_ci	dev_dbg(&sl->dev, "mutex unlocked");
648c2ecf20Sopenharmony_ci	return 1;
658c2ecf20Sopenharmony_ci}
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_cistatic ssize_t state_read(struct file *filp, struct kobject *kobj,
688c2ecf20Sopenharmony_ci			  struct bin_attribute *bin_attr, char *buf, loff_t off,
698c2ecf20Sopenharmony_ci			  size_t count)
708c2ecf20Sopenharmony_ci{
718c2ecf20Sopenharmony_ci	dev_dbg(&kobj_to_w1_slave(kobj)->dev,
728c2ecf20Sopenharmony_ci		"Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
738c2ecf20Sopenharmony_ci		bin_attr->attr.name, kobj, (unsigned int)off, count, buf);
748c2ecf20Sopenharmony_ci	if (count != 1 || off != 0)
758c2ecf20Sopenharmony_ci		return -EFAULT;
768c2ecf20Sopenharmony_ci	return _read_reg(kobj_to_w1_slave(kobj), W1_F29_REG_LOGIG_STATE, buf);
778c2ecf20Sopenharmony_ci}
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_cistatic ssize_t output_read(struct file *filp, struct kobject *kobj,
808c2ecf20Sopenharmony_ci			   struct bin_attribute *bin_attr, char *buf,
818c2ecf20Sopenharmony_ci			   loff_t off, size_t count)
828c2ecf20Sopenharmony_ci{
838c2ecf20Sopenharmony_ci	dev_dbg(&kobj_to_w1_slave(kobj)->dev,
848c2ecf20Sopenharmony_ci		"Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
858c2ecf20Sopenharmony_ci		bin_attr->attr.name, kobj, (unsigned int)off, count, buf);
868c2ecf20Sopenharmony_ci	if (count != 1 || off != 0)
878c2ecf20Sopenharmony_ci		return -EFAULT;
888c2ecf20Sopenharmony_ci	return _read_reg(kobj_to_w1_slave(kobj),
898c2ecf20Sopenharmony_ci					 W1_F29_REG_OUTPUT_LATCH_STATE, buf);
908c2ecf20Sopenharmony_ci}
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_cistatic ssize_t activity_read(struct file *filp, struct kobject *kobj,
938c2ecf20Sopenharmony_ci			     struct bin_attribute *bin_attr, char *buf,
948c2ecf20Sopenharmony_ci			     loff_t off, size_t count)
958c2ecf20Sopenharmony_ci{
968c2ecf20Sopenharmony_ci	dev_dbg(&kobj_to_w1_slave(kobj)->dev,
978c2ecf20Sopenharmony_ci		"Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
988c2ecf20Sopenharmony_ci		bin_attr->attr.name, kobj, (unsigned int)off, count, buf);
998c2ecf20Sopenharmony_ci	if (count != 1 || off != 0)
1008c2ecf20Sopenharmony_ci		return -EFAULT;
1018c2ecf20Sopenharmony_ci	return _read_reg(kobj_to_w1_slave(kobj),
1028c2ecf20Sopenharmony_ci					 W1_F29_REG_ACTIVITY_LATCH_STATE, buf);
1038c2ecf20Sopenharmony_ci}
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_cistatic ssize_t cond_search_mask_read(struct file *filp, struct kobject *kobj,
1068c2ecf20Sopenharmony_ci				     struct bin_attribute *bin_attr, char *buf,
1078c2ecf20Sopenharmony_ci				     loff_t off, size_t count)
1088c2ecf20Sopenharmony_ci{
1098c2ecf20Sopenharmony_ci	dev_dbg(&kobj_to_w1_slave(kobj)->dev,
1108c2ecf20Sopenharmony_ci		"Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
1118c2ecf20Sopenharmony_ci		bin_attr->attr.name, kobj, (unsigned int)off, count, buf);
1128c2ecf20Sopenharmony_ci	if (count != 1 || off != 0)
1138c2ecf20Sopenharmony_ci		return -EFAULT;
1148c2ecf20Sopenharmony_ci	return _read_reg(kobj_to_w1_slave(kobj),
1158c2ecf20Sopenharmony_ci		W1_F29_REG_COND_SEARCH_SELECT_MASK, buf);
1168c2ecf20Sopenharmony_ci}
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_cistatic ssize_t cond_search_polarity_read(struct file *filp,
1198c2ecf20Sopenharmony_ci					 struct kobject *kobj,
1208c2ecf20Sopenharmony_ci					 struct bin_attribute *bin_attr,
1218c2ecf20Sopenharmony_ci					 char *buf, loff_t off, size_t count)
1228c2ecf20Sopenharmony_ci{
1238c2ecf20Sopenharmony_ci	if (count != 1 || off != 0)
1248c2ecf20Sopenharmony_ci		return -EFAULT;
1258c2ecf20Sopenharmony_ci	return _read_reg(kobj_to_w1_slave(kobj),
1268c2ecf20Sopenharmony_ci		W1_F29_REG_COND_SEARCH_POL_SELECT, buf);
1278c2ecf20Sopenharmony_ci}
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_cistatic ssize_t status_control_read(struct file *filp, struct kobject *kobj,
1308c2ecf20Sopenharmony_ci				   struct bin_attribute *bin_attr, char *buf,
1318c2ecf20Sopenharmony_ci				   loff_t off, size_t count)
1328c2ecf20Sopenharmony_ci{
1338c2ecf20Sopenharmony_ci	if (count != 1 || off != 0)
1348c2ecf20Sopenharmony_ci		return -EFAULT;
1358c2ecf20Sopenharmony_ci	return _read_reg(kobj_to_w1_slave(kobj),
1368c2ecf20Sopenharmony_ci		W1_F29_REG_CONTROL_AND_STATUS, buf);
1378c2ecf20Sopenharmony_ci}
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci#ifdef CONFIG_W1_SLAVE_DS2408_READBACK
1408c2ecf20Sopenharmony_cistatic bool optional_read_back_valid(struct w1_slave *sl, u8 expected)
1418c2ecf20Sopenharmony_ci{
1428c2ecf20Sopenharmony_ci	u8 w1_buf[3];
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci	if (w1_reset_resume_command(sl->master))
1458c2ecf20Sopenharmony_ci		return false;
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci	w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS;
1488c2ecf20Sopenharmony_ci	w1_buf[1] = W1_F29_REG_OUTPUT_LATCH_STATE;
1498c2ecf20Sopenharmony_ci	w1_buf[2] = 0;
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci	w1_write_block(sl->master, w1_buf, 3);
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci	return (w1_read_8(sl->master) == expected);
1548c2ecf20Sopenharmony_ci}
1558c2ecf20Sopenharmony_ci#else
1568c2ecf20Sopenharmony_cistatic bool optional_read_back_valid(struct w1_slave *sl, u8 expected)
1578c2ecf20Sopenharmony_ci{
1588c2ecf20Sopenharmony_ci	return true;
1598c2ecf20Sopenharmony_ci}
1608c2ecf20Sopenharmony_ci#endif
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_cistatic ssize_t output_write(struct file *filp, struct kobject *kobj,
1638c2ecf20Sopenharmony_ci			    struct bin_attribute *bin_attr, char *buf,
1648c2ecf20Sopenharmony_ci			    loff_t off, size_t count)
1658c2ecf20Sopenharmony_ci{
1668c2ecf20Sopenharmony_ci	struct w1_slave *sl = kobj_to_w1_slave(kobj);
1678c2ecf20Sopenharmony_ci	u8 w1_buf[3];
1688c2ecf20Sopenharmony_ci	unsigned int retries = W1_F29_RETRIES;
1698c2ecf20Sopenharmony_ci	ssize_t bytes_written = -EIO;
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	if (count != 1 || off != 0)
1728c2ecf20Sopenharmony_ci		return -EFAULT;
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	dev_dbg(&sl->dev, "locking mutex for write_output");
1758c2ecf20Sopenharmony_ci	mutex_lock(&sl->master->bus_mutex);
1768c2ecf20Sopenharmony_ci	dev_dbg(&sl->dev, "mutex locked");
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci	if (w1_reset_select_slave(sl))
1798c2ecf20Sopenharmony_ci		goto out;
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci	do {
1828c2ecf20Sopenharmony_ci		w1_buf[0] = W1_F29_FUNC_CHANN_ACCESS_WRITE;
1838c2ecf20Sopenharmony_ci		w1_buf[1] = *buf;
1848c2ecf20Sopenharmony_ci		w1_buf[2] = ~(*buf);
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci		w1_write_block(sl->master, w1_buf, 3);
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci		if (w1_read_8(sl->master) == W1_F29_SUCCESS_CONFIRM_BYTE &&
1898c2ecf20Sopenharmony_ci		    optional_read_back_valid(sl, *buf)) {
1908c2ecf20Sopenharmony_ci			bytes_written = 1;
1918c2ecf20Sopenharmony_ci			goto out;
1928c2ecf20Sopenharmony_ci		}
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci		if (w1_reset_resume_command(sl->master))
1958c2ecf20Sopenharmony_ci			goto out; /* unrecoverable error */
1968c2ecf20Sopenharmony_ci		/* try again, the slave is ready for a command */
1978c2ecf20Sopenharmony_ci	} while (--retries);
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ciout:
2008c2ecf20Sopenharmony_ci	mutex_unlock(&sl->master->bus_mutex);
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci	dev_dbg(&sl->dev, "%s, mutex unlocked retries:%d\n",
2038c2ecf20Sopenharmony_ci		(bytes_written > 0) ? "succeeded" : "error", retries);
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci	return bytes_written;
2068c2ecf20Sopenharmony_ci}
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci/**
2108c2ecf20Sopenharmony_ci * Writing to the activity file resets the activity latches.
2118c2ecf20Sopenharmony_ci */
2128c2ecf20Sopenharmony_cistatic ssize_t activity_write(struct file *filp, struct kobject *kobj,
2138c2ecf20Sopenharmony_ci			      struct bin_attribute *bin_attr, char *buf,
2148c2ecf20Sopenharmony_ci			      loff_t off, size_t count)
2158c2ecf20Sopenharmony_ci{
2168c2ecf20Sopenharmony_ci	struct w1_slave *sl = kobj_to_w1_slave(kobj);
2178c2ecf20Sopenharmony_ci	unsigned int retries = W1_F29_RETRIES;
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci	if (count != 1 || off != 0)
2208c2ecf20Sopenharmony_ci		return -EFAULT;
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	mutex_lock(&sl->master->bus_mutex);
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	if (w1_reset_select_slave(sl))
2258c2ecf20Sopenharmony_ci		goto error;
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci	while (retries--) {
2288c2ecf20Sopenharmony_ci		w1_write_8(sl->master, W1_F29_FUNC_RESET_ACTIVITY_LATCHES);
2298c2ecf20Sopenharmony_ci		if (w1_read_8(sl->master) == W1_F29_SUCCESS_CONFIRM_BYTE) {
2308c2ecf20Sopenharmony_ci			mutex_unlock(&sl->master->bus_mutex);
2318c2ecf20Sopenharmony_ci			return 1;
2328c2ecf20Sopenharmony_ci		}
2338c2ecf20Sopenharmony_ci		if (w1_reset_resume_command(sl->master))
2348c2ecf20Sopenharmony_ci			goto error;
2358c2ecf20Sopenharmony_ci	}
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_cierror:
2388c2ecf20Sopenharmony_ci	mutex_unlock(&sl->master->bus_mutex);
2398c2ecf20Sopenharmony_ci	return -EIO;
2408c2ecf20Sopenharmony_ci}
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_cistatic ssize_t status_control_write(struct file *filp, struct kobject *kobj,
2438c2ecf20Sopenharmony_ci				    struct bin_attribute *bin_attr, char *buf,
2448c2ecf20Sopenharmony_ci				    loff_t off, size_t count)
2458c2ecf20Sopenharmony_ci{
2468c2ecf20Sopenharmony_ci	struct w1_slave *sl = kobj_to_w1_slave(kobj);
2478c2ecf20Sopenharmony_ci	u8 w1_buf[4];
2488c2ecf20Sopenharmony_ci	unsigned int retries = W1_F29_RETRIES;
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	if (count != 1 || off != 0)
2518c2ecf20Sopenharmony_ci		return -EFAULT;
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	mutex_lock(&sl->master->bus_mutex);
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci	if (w1_reset_select_slave(sl))
2568c2ecf20Sopenharmony_ci		goto error;
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci	while (retries--) {
2598c2ecf20Sopenharmony_ci		w1_buf[0] = W1_F29_FUNC_WRITE_COND_SEARCH_REG;
2608c2ecf20Sopenharmony_ci		w1_buf[1] = W1_F29_REG_CONTROL_AND_STATUS;
2618c2ecf20Sopenharmony_ci		w1_buf[2] = 0;
2628c2ecf20Sopenharmony_ci		w1_buf[3] = *buf;
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci		w1_write_block(sl->master, w1_buf, 4);
2658c2ecf20Sopenharmony_ci		if (w1_reset_resume_command(sl->master))
2668c2ecf20Sopenharmony_ci			goto error;
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci		w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS;
2698c2ecf20Sopenharmony_ci		w1_buf[1] = W1_F29_REG_CONTROL_AND_STATUS;
2708c2ecf20Sopenharmony_ci		w1_buf[2] = 0;
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci		w1_write_block(sl->master, w1_buf, 3);
2738c2ecf20Sopenharmony_ci		if (w1_read_8(sl->master) == *buf) {
2748c2ecf20Sopenharmony_ci			/* success! */
2758c2ecf20Sopenharmony_ci			mutex_unlock(&sl->master->bus_mutex);
2768c2ecf20Sopenharmony_ci			return 1;
2778c2ecf20Sopenharmony_ci		}
2788c2ecf20Sopenharmony_ci	}
2798c2ecf20Sopenharmony_cierror:
2808c2ecf20Sopenharmony_ci	mutex_unlock(&sl->master->bus_mutex);
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci	return -EIO;
2838c2ecf20Sopenharmony_ci}
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci/*
2868c2ecf20Sopenharmony_ci * This is a special sequence we must do to ensure the P0 output is not stuck
2878c2ecf20Sopenharmony_ci * in test mode. This is described in rev 2 of the ds2408's datasheet
2888c2ecf20Sopenharmony_ci * (http://datasheets.maximintegrated.com/en/ds/DS2408.pdf) under
2898c2ecf20Sopenharmony_ci * "APPLICATION INFORMATION/Power-up timing".
2908c2ecf20Sopenharmony_ci */
2918c2ecf20Sopenharmony_cistatic int w1_f29_disable_test_mode(struct w1_slave *sl)
2928c2ecf20Sopenharmony_ci{
2938c2ecf20Sopenharmony_ci	int res;
2948c2ecf20Sopenharmony_ci	u8 magic[10] = {0x96, };
2958c2ecf20Sopenharmony_ci	u64 rn = le64_to_cpu(*((u64*)&sl->reg_num));
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci	memcpy(&magic[1], &rn, 8);
2988c2ecf20Sopenharmony_ci	magic[9] = 0x3C;
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci	mutex_lock(&sl->master->bus_mutex);
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci	res = w1_reset_bus(sl->master);
3038c2ecf20Sopenharmony_ci	if (res)
3048c2ecf20Sopenharmony_ci		goto out;
3058c2ecf20Sopenharmony_ci	w1_write_block(sl->master, magic, ARRAY_SIZE(magic));
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci	res = w1_reset_bus(sl->master);
3088c2ecf20Sopenharmony_ciout:
3098c2ecf20Sopenharmony_ci	mutex_unlock(&sl->master->bus_mutex);
3108c2ecf20Sopenharmony_ci	return res;
3118c2ecf20Sopenharmony_ci}
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_cistatic BIN_ATTR_RO(state, 1);
3148c2ecf20Sopenharmony_cistatic BIN_ATTR_RW(output, 1);
3158c2ecf20Sopenharmony_cistatic BIN_ATTR_RW(activity, 1);
3168c2ecf20Sopenharmony_cistatic BIN_ATTR_RO(cond_search_mask, 1);
3178c2ecf20Sopenharmony_cistatic BIN_ATTR_RO(cond_search_polarity, 1);
3188c2ecf20Sopenharmony_cistatic BIN_ATTR_RW(status_control, 1);
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_cistatic struct bin_attribute *w1_f29_bin_attrs[] = {
3218c2ecf20Sopenharmony_ci	&bin_attr_state,
3228c2ecf20Sopenharmony_ci	&bin_attr_output,
3238c2ecf20Sopenharmony_ci	&bin_attr_activity,
3248c2ecf20Sopenharmony_ci	&bin_attr_cond_search_mask,
3258c2ecf20Sopenharmony_ci	&bin_attr_cond_search_polarity,
3268c2ecf20Sopenharmony_ci	&bin_attr_status_control,
3278c2ecf20Sopenharmony_ci	NULL,
3288c2ecf20Sopenharmony_ci};
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_cistatic const struct attribute_group w1_f29_group = {
3318c2ecf20Sopenharmony_ci	.bin_attrs = w1_f29_bin_attrs,
3328c2ecf20Sopenharmony_ci};
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_cistatic const struct attribute_group *w1_f29_groups[] = {
3358c2ecf20Sopenharmony_ci	&w1_f29_group,
3368c2ecf20Sopenharmony_ci	NULL,
3378c2ecf20Sopenharmony_ci};
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_cistatic const struct w1_family_ops w1_f29_fops = {
3408c2ecf20Sopenharmony_ci	.add_slave      = w1_f29_disable_test_mode,
3418c2ecf20Sopenharmony_ci	.groups		= w1_f29_groups,
3428c2ecf20Sopenharmony_ci};
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_cistatic struct w1_family w1_family_29 = {
3458c2ecf20Sopenharmony_ci	.fid = W1_FAMILY_DS2408,
3468c2ecf20Sopenharmony_ci	.fops = &w1_f29_fops,
3478c2ecf20Sopenharmony_ci};
3488c2ecf20Sopenharmony_cimodule_w1_family(w1_family_29);
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ciMODULE_AUTHOR("Jean-Francois Dagenais <dagenaisj@sonatest.com>");
3518c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("w1 family 29 driver for DS2408 8 Pin IO");
3528c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
3538c2ecf20Sopenharmony_ciMODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_DS2408));
354