/*
 * Copyright (c) 2022 Thomas Stranger
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @brief Common functions for Maxim DS2477,DS2485 1-Wire Masters
 */

#include "w1_ds2477_85_common.h"

#include <zephyr/drivers/i2c.h>
#include <zephyr/drivers/w1.h>
#include <zephyr/logging/log.h>
#include <zephyr/kernel.h>

LOG_MODULE_REGISTER(w1_ds2477_85, CONFIG_W1_LOG_LEVEL);

int ds2477_85_write_port_config(const struct device *dev, uint8_t reg, uint16_t value)
{
	const struct w1_ds2477_85_config *cfg = dev->config;
	uint8_t buf[5] = {CMD_WR_W1_PORT_CFG, CMD_WR_W1_PORT_CFG_LEN, reg};
	int ret;

	__ASSERT_NO_MSG(reg <= PORT_REG_COUNT);

	sys_put_le16(value, &buf[3]);
	ret = i2c_write_dt(&cfg->i2c_spec, buf, (CMD_WR_W1_PORT_CFG_LEN + CMD_OVERHEAD_LEN));
	if (ret < 0) {
		return ret;
	}

	k_usleep(cfg->t_op_us);

	ret = i2c_read_dt(&cfg->i2c_spec, buf, 2);
	if (ret < 0) {
		return ret;
	}
	if ((buf[0] != 1) || (buf[1] != DS2477_88_RES_SUCCESS)) {
		return -EIO;
	}

	return 0;
}

int ds2477_85_read_port_config(const struct device *dev, uint8_t reg, uint16_t *value)
{
	const struct w1_ds2477_85_config *cfg = dev->config;
	uint8_t buf[4] = {CMD_RD_W1_PORT_CFG, CMD_RD_W1_PORT_CFG_LEN, reg};
	int ret;

	__ASSERT_NO_MSG(value != NULL && reg <= PORT_REG_COUNT);

	ret = i2c_write_dt(&cfg->i2c_spec, buf, (CMD_RD_W1_PORT_CFG_LEN + CMD_OVERHEAD_LEN));
	if (ret < 0) {
		return ret;
	}

	k_usleep(cfg->t_op_us);

	ret = i2c_read_dt(&cfg->i2c_spec, buf, 4);
	if (ret < 0) {
		return ret;
	}
	if ((buf[0] != 3) || (buf[1] != DS2477_88_RES_SUCCESS)) {
		return -EIO;
	}

	*value = sys_get_le16(&buf[2]);

	return 0;
}

int ds2477_85_reset_master(const struct device *dev)
{
	const struct w1_ds2477_85_config *cfg = dev->config;
	uint8_t buf[2] = {CMD_MASTER_RESET};
	int ret;

	ret = i2c_write_dt(&cfg->i2c_spec, buf, 1);
	if (ret < 0) {
		LOG_ERR("initiate reset failed");
		return ret;
	}

	k_usleep(cfg->t_op_us);

	ret = i2c_read_dt(&cfg->i2c_spec, buf, 2);
	if (ret < 0) {
		return ret;
	}
	if ((buf[0] != 1) || (buf[1] != DS2477_88_RES_SUCCESS)) {
		return -EIO;
	}

	return 0;
}

int ds2477_85_reset_bus(const struct device *dev)
{
	const struct w1_ds2477_85_config *cfg = dev->config;
	struct w1_ds2477_85_data *data = dev->data;
	uint16_t delay_us = cfg->mode_timing[data->master_reg.od_active].t_reset;
	uint8_t tx_data;
	uint8_t rx_data;
	int ret;

	tx_data = data->master_reg.od_active ? BIT(3) : BIT(7);
	ret = cfg->w1_script_cmd(dev, delay_us, SCRIPT_OW_RESET, &tx_data, 1, &rx_data, 1);

	switch (ret) {
	case DS2477_88_RES_COMM_FAILURE:
		/* presence not detected */
		return 0;
	case DS2477_88_RES_SUCCESS:
		/* at least 1 device present */
		return 1;
	default:
		return -EIO;
	}
}

int ds2477_85_read_bit(const struct device *dev)
{
	const struct w1_ds2477_85_config *cfg = dev->config;
	struct w1_ds2477_85_data *data = dev->data;
	uint16_t delay_us = cfg->mode_timing[data->master_reg.od_active].t_slot;
	uint8_t rx_data;
	int ret;

	ret = cfg->w1_script_cmd(dev, delay_us, SCRIPT_OW_READ_BIT, NULL, 0, &rx_data, 1);
	if (ret != DS2477_88_RES_SUCCESS) {
		return -EIO;
	}

	return (rx_data & BIT(5)) ? 1 : 0;
}

int ds2477_85_write_bit(const struct device *dev, const bool bit)
{
	const struct w1_ds2477_85_config *cfg = dev->config;
	struct w1_ds2477_85_data *data = dev->data;
	uint16_t delay_us = cfg->mode_timing[data->master_reg.od_active].t_slot;
	uint8_t tx_data = (uint8_t)bit;
	uint8_t rx_data;
	int ret;

	ret = cfg->w1_script_cmd(dev, delay_us, SCRIPT_OW_WRITE_BIT, &tx_data, 1, &rx_data, 1);
	if (ret != DS2477_88_RES_SUCCESS) {
		return -EIO;
	}

	return 0;
}

int ds2477_85_read_byte(const struct device *dev)
{
	const struct w1_ds2477_85_config *cfg = dev->config;
	struct w1_ds2477_85_data *data = dev->data;
	uint16_t delay_us = cfg->mode_timing[data->master_reg.od_active].t_slot * 8;
	uint8_t rx_data;
	int ret;

	ret = cfg->w1_script_cmd(dev, delay_us, SCRIPT_OW_READ_BYTE, NULL, 0, &rx_data, 1);
	if (ret != DS2477_88_RES_SUCCESS) {
		return -EIO;
	}

	return rx_data;
}

int ds2477_85_write_byte(const struct device *dev, const uint8_t tx_byte)
{
	const struct w1_ds2477_85_config *cfg = dev->config;
	struct w1_ds2477_85_data *data = dev->data;
	uint16_t delay_us = cfg->mode_timing[data->master_reg.od_active].t_slot * 8;
	uint8_t rx_data;
	int ret;

	ret = cfg->w1_script_cmd(dev, delay_us, SCRIPT_OW_WRITE_BYTE, &tx_byte, 1, &rx_data, 1);
	if (ret != DS2477_88_RES_SUCCESS) {
		return -EIO;
	}

	return 0;
}

int ds2477_85_write_block(const struct device *dev, const uint8_t *buffer, size_t tx_len)
{
	const struct w1_ds2477_85_config *cfg = dev->config;
	struct w1_ds2477_85_data *data = dev->data;
	int w1_timing = cfg->mode_timing[data->master_reg.od_active].t_slot * 8 * tx_len;
	uint8_t buf[3] = {CMD_WR_BLOCK, (tx_len + CMD_WR_BLOCK_LEN), 0};
	struct i2c_msg tx_msg[2] = {
		{.buf = buf, .len = (CMD_WR_BLOCK_LEN + CMD_OVERHEAD_LEN), .flags = I2C_MSG_WRITE},
		{.buf = (uint8_t *)buffer, .len = tx_len, .flags = (I2C_MSG_WRITE | I2C_MSG_STOP)},
	};
	int ret;

	__ASSERT_NO_MSG(tx_len <= MAX_BLOCK_LEN);

	if (tx_len == 0) {
		return 0;
	}

	ret = i2c_transfer_dt(&cfg->i2c_spec, tx_msg, 2);
	if (ret < 0) {
		LOG_ERR("write block fail: %x", ret);
		return ret;
	}

	k_usleep(cfg->t_op_us + (cfg->t_seq_us * tx_len) +  w1_timing);

	ret = i2c_read_dt(&cfg->i2c_spec, buf, 2);
	if (ret < 0) {
		return ret;
	}
	if ((buf[0] != 1) || (buf[1] != DS2477_88_RES_SUCCESS)) {
		return -EIO;
	}

	return 0;
}

int ds2477_85_read_block(const struct device *dev, uint8_t *buffer, size_t rx_len)
{
	const struct w1_ds2477_85_config *cfg = dev->config;
	struct w1_ds2477_85_data *data = dev->data;
	int w1_timing = cfg->mode_timing[data->master_reg.od_active].t_slot * 8 * rx_len;
	uint8_t buf[3] = {CMD_RD_BLOCK, CMD_RD_BLOCK_LEN, rx_len};
	struct i2c_msg rx_msg[2] = {
		{.buf = buf, .len = 2, .flags = I2C_MSG_READ},
		{.buf = buffer, .len = rx_len, .flags = (I2C_MSG_READ | I2C_MSG_STOP)}
	};
	int ret;

	__ASSERT_NO_MSG(rx_len <= MAX_BLOCK_LEN);

	if (rx_len == 0) {
		return 0;
	}

	ret = i2c_write_dt(&cfg->i2c_spec, buf, (CMD_RD_BLOCK_LEN + CMD_OVERHEAD_LEN));
	if (ret < 0) {
		LOG_ERR("read block fail: %x", ret);
		return ret;
	}

	k_usleep(cfg->t_op_us + (cfg->t_seq_us * rx_len) +  w1_timing);

	ret = i2c_transfer_dt(&cfg->i2c_spec, rx_msg, 2);
	if (ret < 0) {
		return ret;
	}
	if (buf[1] != DS2477_88_RES_SUCCESS) {
		return -EIO;
	}

	return 0;
}

int ds2477_85_configure(const struct device *dev, enum w1_settings_type type, uint32_t value)
{
	struct w1_ds2477_85_data *data = dev->data;

	switch (type) {
	case W1_SETTING_SPEED:
		__ASSERT_NO_MSG(value <= 1);
		data->master_reg.od_active = value;
		break;
	default:
		return -EINVAL;
	}

	return ds2477_85_write_port_config(dev, PORT_REG_MASTER_CONFIGURATION,
					   data->master_reg.value);
}

int w1_ds2477_85_init(const struct device *dev)
{
	const struct w1_ds2477_85_config *cfg = dev->config;
	struct w1_ds2477_85_data *data = dev->data;

	data->master_reg.apu = cfg->apu;

	if (ds2477_85_write_port_config(dev, PORT_REG_MASTER_CONFIGURATION,
					data->master_reg.value) < 0) {
		return -EIO;
	}

	if (ds2477_85_write_port_config(dev, PORT_REG_RPUP_BUF, cfg->rpup_buf) < 0) {
		return -EIO;
	}

	if (ds2477_85_write_port_config(dev, PORT_REG_PDSLEW, cfg->pdslew) < 0) {
		return -EIO;
	}

	LOG_DBG("cfg: rpup_buf=%02x, pdslew:%02x", cfg->rpup_buf, cfg->pdslew);

	/* RPUP/BUF configuration is applied after a bus reset */
	(void)ds2477_85_reset_bus(dev);

	LOG_DBG("w1-ds2477/85 init; %d slave devices",
		cfg->master_config.slave_count);

	return 0;
}
