1 /*
2  * Copyright (c) 2022 Caspar Friedrich <c.s.w.friedrich@gmail.com>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include "w1_ds2482_84_common.h"
8 
9 #include <zephyr/devicetree.h>
10 #include <zephyr/drivers/gpio.h>
11 #include <zephyr/drivers/i2c.h>
12 #include <zephyr/drivers/w1.h>
13 #include <zephyr/kernel.h>
14 #include <zephyr/logging/log.h>
15 #include <zephyr/pm/device.h>
16 
17 #define DT_DRV_COMPAT maxim_ds2484
18 
19 LOG_MODULE_REGISTER(ds2484, CONFIG_W1_LOG_LEVEL);
20 
21 struct ds2484_config {
22 	struct w1_master_config w1_config;
23 	const struct i2c_dt_spec i2c_spec;
24 	const struct gpio_dt_spec slpz_spec;
25 	bool apu;
26 };
27 
28 struct ds2484_data {
29 	struct w1_master_data w1_data;
30 	uint8_t reg_device_config;
31 };
32 
ds2484_reset_bus(const struct device * dev)33 static int ds2484_reset_bus(const struct device *dev)
34 {
35 	const struct ds2484_config *config = dev->config;
36 
37 	return ds2482_84_reset_bus(&config->i2c_spec);
38 }
39 
ds2484_read_bit(const struct device * dev)40 static int ds2484_read_bit(const struct device *dev)
41 {
42 	const struct ds2484_config *config = dev->config;
43 
44 	return ds2482_84_read_bit(&config->i2c_spec);
45 }
46 
ds2484_write_bit(const struct device * dev,bool bit)47 static int ds2484_write_bit(const struct device *dev, bool bit)
48 {
49 	const struct ds2484_config *config = dev->config;
50 
51 	return ds2482_84_write_bit(&config->i2c_spec, bit);
52 }
53 
ds2484_read_byte(const struct device * dev)54 static int ds2484_read_byte(const struct device *dev)
55 {
56 	const struct ds2484_config *config = dev->config;
57 
58 	return ds2482_84_read_byte(&config->i2c_spec);
59 }
60 
ds2484_write_byte(const struct device * dev,uint8_t byte)61 static int ds2484_write_byte(const struct device *dev, uint8_t byte)
62 {
63 	const struct ds2484_config *config = dev->config;
64 
65 	return ds2482_84_write_byte(&config->i2c_spec, byte);
66 }
67 
ds2484_configure(const struct device * dev,enum w1_settings_type type,uint32_t value)68 static int ds2484_configure(const struct device *dev, enum w1_settings_type type, uint32_t value)
69 {
70 	const struct ds2484_config *config = dev->config;
71 	struct ds2484_data *data = dev->data;
72 
73 	switch (type) {
74 	case W1_SETTING_SPEED:
75 		WRITE_BIT(data->reg_device_config, DEVICE_1WS_pos, value);
76 		break;
77 	case W1_SETTING_STRONG_PULLUP:
78 		WRITE_BIT(data->reg_device_config, DEVICE_SPU_pos, value);
79 		break;
80 	default:
81 		return -EINVAL;
82 	}
83 
84 	return ds2482_84_write_config(&config->i2c_spec, data->reg_device_config);
85 }
86 
87 #ifdef CONFIG_PM_DEVICE
ds2484_pm_control(const struct device * dev,enum pm_device_action action)88 static int ds2484_pm_control(const struct device *dev, enum pm_device_action action)
89 {
90 	const struct ds2484_config *config = dev->config;
91 
92 	switch (action) {
93 	case PM_DEVICE_ACTION_SUSPEND:
94 		if (!config->slpz_spec.port) {
95 			return -ENOTSUP;
96 		}
97 		return gpio_pin_set_dt(&config->slpz_spec, 1);
98 	case PM_DEVICE_ACTION_RESUME:
99 		if (!config->slpz_spec.port) {
100 			return -ENOTSUP;
101 		}
102 		return gpio_pin_set_dt(&config->slpz_spec, 0);
103 	default:
104 		return -ENOTSUP;
105 	};
106 
107 	return 0;
108 }
109 #endif /* CONFIG_PM_DEVICE */
110 
ds2484_init(const struct device * dev)111 static int ds2484_init(const struct device *dev)
112 {
113 	int ret;
114 
115 	const struct ds2484_config *config = dev->config;
116 	struct ds2484_data *data = dev->data;
117 
118 	if (config->slpz_spec.port) {
119 		if (!gpio_is_ready_dt(&config->slpz_spec)) {
120 			LOG_ERR("Port (SLPZ) not ready");
121 			return -ENODEV;
122 		}
123 
124 		ret = gpio_pin_configure_dt(&config->slpz_spec, GPIO_OUTPUT_INACTIVE);
125 		if (ret < 0) {
126 			LOG_ERR("Pin configuration (SLPZ) failed: %d", ret);
127 			return ret;
128 		}
129 	}
130 
131 	if (!device_is_ready(config->i2c_spec.bus)) {
132 		return -ENODEV;
133 	}
134 
135 	ret = ds2482_84_reset_device(&config->i2c_spec);
136 	if (ret < 0) {
137 		LOG_ERR("Device reset failed: %d", ret);
138 		return ret;
139 	}
140 
141 	WRITE_BIT(data->reg_device_config, DEVICE_APU_pos, config->apu);
142 
143 	ret = ds2482_84_write_config(&config->i2c_spec, data->reg_device_config);
144 	if (ret < 0) {
145 		LOG_ERR("Device config update failed: %d", ret);
146 		return ret;
147 	}
148 
149 	return 0;
150 }
151 
152 static DEVICE_API(w1, ds2484_driver_api) = {
153 	.reset_bus = ds2484_reset_bus,
154 	.read_bit = ds2484_read_bit,
155 	.write_bit = ds2484_write_bit,
156 	.read_byte = ds2484_read_byte,
157 	.write_byte = ds2484_write_byte,
158 	.configure = ds2484_configure,
159 };
160 
161 #define DS2484_INIT(inst)                                                                          \
162 	static const struct ds2484_config inst_##inst##_config = {                                 \
163 		.w1_config.slave_count = W1_INST_SLAVE_COUNT(inst),                                \
164 		.i2c_spec = I2C_DT_SPEC_INST_GET(inst),                                            \
165 		.slpz_spec = GPIO_DT_SPEC_INST_GET_OR(inst, slpz_gpios, {0}),                      \
166 		.apu = DT_INST_PROP(inst, active_pullup),                                          \
167 	};                                                                                         \
168 	static struct ds2484_data inst_##inst##_data;                                              \
169 	PM_DEVICE_DT_INST_DEFINE(inst, ds2484_pm_control);                                         \
170 	DEVICE_DT_INST_DEFINE(inst, ds2484_init, PM_DEVICE_DT_INST_GET(inst), &inst_##inst##_data, \
171 			      &inst_##inst##_config, POST_KERNEL, CONFIG_W1_INIT_PRIORITY,         \
172 			      &ds2484_driver_api);
173 
174 DT_INST_FOREACH_STATUS_OKAY(DS2484_INIT)
175 
176 /*
177  * Make sure that this driver is not initialized before the i2c bus is available
178  */
179 BUILD_ASSERT(CONFIG_W1_INIT_PRIORITY > CONFIG_I2C_INIT_PRIORITY);
180