2023-03-09 21:19:48 +08:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2023 Caspar Friedrich <c.s.w.friedrich@gmail.com>
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "w1_ds2482-800.h"
|
|
|
|
#include "w1_ds2482_84_common.h"
|
|
|
|
|
|
|
|
#include <zephyr/devicetree.h>
|
|
|
|
#include <zephyr/drivers/i2c.h>
|
|
|
|
#include <zephyr/drivers/w1.h>
|
|
|
|
#include <zephyr/logging/log.h>
|
|
|
|
|
|
|
|
#define DT_DRV_COMPAT maxim_ds2482_800_channel
|
|
|
|
|
|
|
|
LOG_MODULE_DECLARE(ds2482, CONFIG_W1_LOG_LEVEL);
|
|
|
|
|
|
|
|
struct ds2482_config {
|
|
|
|
struct w1_master_config w1_config;
|
|
|
|
const struct device *parent;
|
|
|
|
const struct i2c_dt_spec i2c_spec;
|
|
|
|
uint8_t reg_channel;
|
|
|
|
uint8_t reg_channel_rb;
|
|
|
|
uint8_t reg_config;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ds2482_data {
|
|
|
|
struct w1_master_data w1_data;
|
|
|
|
};
|
|
|
|
|
|
|
|
static int ds2482_reset_bus(const struct device *dev)
|
|
|
|
{
|
|
|
|
const struct ds2482_config *config = dev->config;
|
|
|
|
|
|
|
|
return ds2482_84_reset_bus(&config->i2c_spec);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ds2482_read_bit(const struct device *dev)
|
|
|
|
{
|
|
|
|
const struct ds2482_config *config = dev->config;
|
|
|
|
|
|
|
|
return ds2482_84_read_bit(&config->i2c_spec);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ds2482_write_bit(const struct device *dev, bool bit)
|
|
|
|
{
|
|
|
|
const struct ds2482_config *config = dev->config;
|
|
|
|
|
|
|
|
return ds2482_84_write_bit(&config->i2c_spec, bit);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ds2482_read_byte(const struct device *dev)
|
|
|
|
{
|
|
|
|
const struct ds2482_config *config = dev->config;
|
|
|
|
|
|
|
|
return ds2482_84_read_byte(&config->i2c_spec);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ds2482_write_byte(const struct device *dev, uint8_t byte)
|
|
|
|
{
|
|
|
|
const struct ds2482_config *config = dev->config;
|
|
|
|
|
|
|
|
return ds2482_84_write_byte(&config->i2c_spec, byte);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ds2482_configure(const struct device *dev, enum w1_settings_type type, uint32_t value)
|
|
|
|
{
|
|
|
|
const struct ds2482_config *config = dev->config;
|
|
|
|
|
|
|
|
uint8_t reg_config = config->reg_config;
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case W1_SETTING_SPEED:
|
|
|
|
WRITE_BIT(reg_config, DEVICE_1WS_pos, value);
|
|
|
|
break;
|
|
|
|
case W1_SETTING_STRONG_PULLUP:
|
|
|
|
WRITE_BIT(reg_config, DEVICE_SPU_pos, value);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ds2482_84_write_config(&config->i2c_spec, reg_config);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ds2482_set_channel(const struct i2c_dt_spec *spec, uint8_t channel, uint8_t channel_rb)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
uint8_t reg = channel;
|
|
|
|
|
|
|
|
ret = ds2482_84_write(spec, CMD_CHSL, ®);
|
|
|
|
if (ret < 0) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = ds2482_84_read(spec, REG_NONE, ®);
|
|
|
|
if (ret < 0) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (reg == channel_rb) ? 0 : -EIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ds2482_change_bus_lock(const struct device *dev, bool lock)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
const struct ds2482_config *config = dev->config;
|
|
|
|
|
|
|
|
ret = ds2482_change_bus_lock_impl(config->parent, lock);
|
|
|
|
if (ret < 0) {
|
|
|
|
LOG_ERR("Failed to acquire bus lock: %d", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!lock) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set channel for subsequent operations
|
|
|
|
*/
|
|
|
|
ret = ds2482_set_channel(&config->i2c_spec, config->reg_channel, config->reg_channel_rb);
|
|
|
|
if (ret < 0) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Restore default channel configuration
|
|
|
|
*/
|
|
|
|
ret = ds2482_84_write_config(&config->i2c_spec, config->reg_config);
|
|
|
|
if (ret < 0) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ds2482_init(const struct device *dev)
|
|
|
|
{
|
|
|
|
const struct ds2482_config *config = dev->config;
|
|
|
|
|
|
|
|
if (!device_is_ready(config->parent)) {
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct w1_driver_api ds2482_driver_api = {
|
|
|
|
.reset_bus = ds2482_reset_bus,
|
|
|
|
.read_bit = ds2482_read_bit,
|
|
|
|
.write_bit = ds2482_write_bit,
|
|
|
|
.read_byte = ds2482_read_byte,
|
|
|
|
.write_byte = ds2482_write_byte,
|
|
|
|
.configure = ds2482_configure,
|
|
|
|
.change_bus_lock = ds2482_change_bus_lock,
|
|
|
|
};
|
|
|
|
|
|
|
|
#define DS2482_CHANNEL_INIT(inst) \
|
|
|
|
static const struct ds2482_config inst_##inst##_config = { \
|
|
|
|
.w1_config.slave_count = W1_INST_SLAVE_COUNT(inst), \
|
|
|
|
.parent = DEVICE_DT_GET(DT_INST_PARENT(inst)), \
|
|
|
|
.i2c_spec = I2C_DT_SPEC_GET(DT_INST_PARENT(inst)), \
|
2024-09-20 21:01:04 +08:00
|
|
|
.reg_channel = UTIL_CAT(CHSL_IO, DT_INST_REG_ADDR_RAW(inst)), \
|
|
|
|
.reg_channel_rb = UTIL_CAT(CHSL_RB_IO, DT_INST_REG_ADDR_RAW(inst)), \
|
2023-03-09 21:19:48 +08:00
|
|
|
.reg_config = DT_INST_PROP(inst, active_pullup) << DEVICE_APU_pos, \
|
|
|
|
}; \
|
|
|
|
static struct ds2482_data inst_##inst##_data = {0}; \
|
|
|
|
DEVICE_DT_INST_DEFINE(inst, ds2482_init, NULL, &inst_##inst##_data, &inst_##inst##_config, \
|
|
|
|
POST_KERNEL, CONFIG_W1_INIT_PRIORITY, &ds2482_driver_api);
|
|
|
|
|
|
|
|
DT_INST_FOREACH_STATUS_OKAY(DS2482_CHANNEL_INIT)
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Make sure that this driver is not initialized before the i2c bus is available
|
|
|
|
*/
|
|
|
|
BUILD_ASSERT(CONFIG_W1_INIT_PRIORITY > CONFIG_I2C_INIT_PRIORITY);
|