1 /*
2  * Copyright (c) 2023 Caspar Friedrich <c.s.w.friedrich@gmail.com>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include "w1_ds2482-800.h"
8 #include "w1_ds2482_84_common.h"
9 
10 #include <zephyr/devicetree.h>
11 #include <zephyr/drivers/i2c.h>
12 #include <zephyr/drivers/w1.h>
13 #include <zephyr/logging/log.h>
14 
15 #define DT_DRV_COMPAT maxim_ds2482_800_channel
16 
17 LOG_MODULE_DECLARE(ds2482, CONFIG_W1_LOG_LEVEL);
18 
19 struct ds2482_config {
20 	struct w1_master_config w1_config;
21 	const struct device *parent;
22 	const struct i2c_dt_spec i2c_spec;
23 	uint8_t reg_channel;
24 	uint8_t reg_channel_rb;
25 	uint8_t reg_config;
26 };
27 
28 struct ds2482_data {
29 	struct w1_master_data w1_data;
30 };
31 
ds2482_reset_bus(const struct device * dev)32 static int ds2482_reset_bus(const struct device *dev)
33 {
34 	const struct ds2482_config *config = dev->config;
35 
36 	return ds2482_84_reset_bus(&config->i2c_spec);
37 }
38 
ds2482_read_bit(const struct device * dev)39 static int ds2482_read_bit(const struct device *dev)
40 {
41 	const struct ds2482_config *config = dev->config;
42 
43 	return ds2482_84_read_bit(&config->i2c_spec);
44 }
45 
ds2482_write_bit(const struct device * dev,bool bit)46 static int ds2482_write_bit(const struct device *dev, bool bit)
47 {
48 	const struct ds2482_config *config = dev->config;
49 
50 	return ds2482_84_write_bit(&config->i2c_spec, bit);
51 }
52 
ds2482_read_byte(const struct device * dev)53 static int ds2482_read_byte(const struct device *dev)
54 {
55 	const struct ds2482_config *config = dev->config;
56 
57 	return ds2482_84_read_byte(&config->i2c_spec);
58 }
59 
ds2482_write_byte(const struct device * dev,uint8_t byte)60 static int ds2482_write_byte(const struct device *dev, uint8_t byte)
61 {
62 	const struct ds2482_config *config = dev->config;
63 
64 	return ds2482_84_write_byte(&config->i2c_spec, byte);
65 }
66 
ds2482_configure(const struct device * dev,enum w1_settings_type type,uint32_t value)67 static int ds2482_configure(const struct device *dev, enum w1_settings_type type, uint32_t value)
68 {
69 	const struct ds2482_config *config = dev->config;
70 
71 	uint8_t reg_config = config->reg_config;
72 
73 	switch (type) {
74 	case W1_SETTING_SPEED:
75 		WRITE_BIT(reg_config, DEVICE_1WS_pos, value);
76 		break;
77 	case W1_SETTING_STRONG_PULLUP:
78 		WRITE_BIT(reg_config, DEVICE_SPU_pos, value);
79 		break;
80 	default:
81 		return -EINVAL;
82 	}
83 
84 	return ds2482_84_write_config(&config->i2c_spec, reg_config);
85 }
86 
ds2482_set_channel(const struct i2c_dt_spec * spec,uint8_t channel,uint8_t channel_rb)87 static int ds2482_set_channel(const struct i2c_dt_spec *spec, uint8_t channel, uint8_t channel_rb)
88 {
89 	int ret;
90 
91 	uint8_t reg = channel;
92 
93 	ret = ds2482_84_write(spec, CMD_CHSL, &reg);
94 	if (ret < 0) {
95 		return ret;
96 	}
97 
98 	ret = ds2482_84_read(spec, REG_NONE, &reg);
99 	if (ret < 0) {
100 		return ret;
101 	}
102 
103 	return (reg == channel_rb) ? 0 : -EIO;
104 }
105 
ds2482_change_bus_lock(const struct device * dev,bool lock)106 static int ds2482_change_bus_lock(const struct device *dev, bool lock)
107 {
108 	int ret;
109 
110 	const struct ds2482_config *config = dev->config;
111 
112 	ret = ds2482_change_bus_lock_impl(config->parent, lock);
113 	if (ret < 0) {
114 		LOG_ERR("Failed to acquire bus lock: %d", ret);
115 		return ret;
116 	}
117 
118 	if (!lock) {
119 		return 0;
120 	}
121 
122 	/*
123 	 * Set channel for subsequent operations
124 	 */
125 	ret = ds2482_set_channel(&config->i2c_spec, config->reg_channel, config->reg_channel_rb);
126 	if (ret < 0) {
127 		return ret;
128 	}
129 
130 	/*
131 	 * Restore default channel configuration
132 	 */
133 	ret = ds2482_84_write_config(&config->i2c_spec, config->reg_config);
134 	if (ret < 0) {
135 		return ret;
136 	}
137 
138 	return 0;
139 }
140 
ds2482_init(const struct device * dev)141 static int ds2482_init(const struct device *dev)
142 {
143 	const struct ds2482_config *config = dev->config;
144 
145 	if (!device_is_ready(config->parent)) {
146 		return -ENODEV;
147 	}
148 
149 	return 0;
150 }
151 
152 static DEVICE_API(w1, ds2482_driver_api) = {
153 	.reset_bus = ds2482_reset_bus,
154 	.read_bit = ds2482_read_bit,
155 	.write_bit = ds2482_write_bit,
156 	.read_byte = ds2482_read_byte,
157 	.write_byte = ds2482_write_byte,
158 	.configure = ds2482_configure,
159 	.change_bus_lock = ds2482_change_bus_lock,
160 };
161 
162 #define DS2482_CHANNEL_INIT(inst)                                                                  \
163 	static const struct ds2482_config inst_##inst##_config = {                                 \
164 		.w1_config.slave_count = W1_INST_SLAVE_COUNT(inst),                                \
165 		.parent = DEVICE_DT_GET(DT_INST_PARENT(inst)),                                     \
166 		.i2c_spec = I2C_DT_SPEC_GET(DT_INST_PARENT(inst)),                                 \
167 		.reg_channel = UTIL_CAT(CHSL_IO, DT_INST_REG_ADDR_RAW(inst)),                      \
168 		.reg_channel_rb = UTIL_CAT(CHSL_RB_IO, DT_INST_REG_ADDR_RAW(inst)),                \
169 		.reg_config = DT_INST_PROP(inst, active_pullup) << DEVICE_APU_pos,                 \
170 	};                                                                                         \
171 	static struct ds2482_data inst_##inst##_data = {0};                                        \
172 	DEVICE_DT_INST_DEFINE(inst, ds2482_init, NULL, &inst_##inst##_data, &inst_##inst##_config, \
173 			      POST_KERNEL, CONFIG_W1_INIT_PRIORITY, &ds2482_driver_api);
174 
175 DT_INST_FOREACH_STATUS_OKAY(DS2482_CHANNEL_INIT)
176 
177 /*
178  * Make sure that this driver is not initialized before the i2c bus is available
179  */
180 BUILD_ASSERT(CONFIG_W1_INIT_PRIORITY > CONFIG_I2C_INIT_PRIORITY);
181