/*
 * Copyright (c) 2023 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

#define DT_DRV_COMPAT asahi_kasei_akm09918c

#include <zephyr/device.h>
#include <zephyr/drivers/i2c.h>
#include <zephyr/kernel.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/sys/__assert.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/sys/util.h>
#include <zephyr/logging/log.h>

#include "akm09918c.h"
#include "akm09918c_reg.h"

LOG_MODULE_REGISTER(AKM09918C, CONFIG_SENSOR_LOG_LEVEL);

static int akm09918c_sample_fetch(const struct device *dev, enum sensor_channel chan)
{
	struct akm09918c_data *data = dev->data;
	const struct akm09918c_config *cfg = dev->config;
	uint8_t buf[9] = {0};

	if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_MAGN_X && chan != SENSOR_CHAN_MAGN_Y &&
	    chan != SENSOR_CHAN_MAGN_Z && chan != SENSOR_CHAN_MAGN_XYZ) {
		LOG_WRN("Invalid channel %d", chan);
		return -EINVAL;
	}

	if (data->mode == AKM09918C_CNTL2_PWR_DOWN) {
		if (i2c_reg_write_byte_dt(&cfg->i2c, AKM09918C_REG_CNTL2,
					  AKM09918C_CNTL2_SINGLE_MEASURE) != 0) {
			LOG_ERR("Failed to start measurement.");
			return -EIO;
		}

		/* Wait for sample */
		LOG_DBG("Waiting for sample...");
		k_usleep(AKM09918C_MEASURE_TIME_US);
	}

	/* We have to read through the TMPS register or the data_ready bit won't clear */
	if (i2c_burst_read_dt(&cfg->i2c, AKM09918C_REG_ST1, buf, ARRAY_SIZE(buf)) != 0) {
		LOG_ERR("Failed to read sample data.");
		return -EIO;
	}

	if (FIELD_GET(AKM09918C_ST1_DRDY, buf[0]) == 0) {
		LOG_ERR("Data not ready, st1=0x%02x", buf[0]);
		return -EBUSY;
	}

	data->x_sample = sys_le16_to_cpu(buf[1] | (buf[2] << 8));
	data->y_sample = sys_le16_to_cpu(buf[3] | (buf[4] << 8));
	data->z_sample = sys_le16_to_cpu(buf[5] | (buf[6] << 8));

	return 0;
}

static void akm09918c_convert(struct sensor_value *val, int16_t sample)
{
	int64_t conv_val = sample * AKM09918C_MICRO_GAUSS_PER_BIT;

	val->val1 = conv_val / 1000000;
	val->val2 = conv_val - (val->val1 * 1000000);
}

static int akm09918c_channel_get(const struct device *dev, enum sensor_channel chan,
				 struct sensor_value *val)
{
	struct akm09918c_data *data = dev->data;

	if (chan == SENSOR_CHAN_MAGN_XYZ) {
		akm09918c_convert(val, data->x_sample);
		akm09918c_convert(val + 1, data->y_sample);
		akm09918c_convert(val + 2, data->z_sample);
	} else if (chan == SENSOR_CHAN_MAGN_X) {
		akm09918c_convert(val, data->x_sample);
	} else if (chan == SENSOR_CHAN_MAGN_Y) {
		akm09918c_convert(val, data->y_sample);
	} else if (chan == SENSOR_CHAN_MAGN_Z) {
		akm09918c_convert(val, data->z_sample);
	} else {
		LOG_WRN("Invalid channel %d", chan);
		return -EINVAL;
	}

	return 0;
}

static int akm09918c_attr_get(const struct device *dev, enum sensor_channel chan,
			      enum sensor_attribute attr, struct sensor_value *val)
{
	struct akm09918c_data *data = dev->data;

	switch (chan) {
	case SENSOR_CHAN_MAGN_X:
	case SENSOR_CHAN_MAGN_Y:
	case SENSOR_CHAN_MAGN_Z:
	case SENSOR_CHAN_MAGN_XYZ:
		if (attr != SENSOR_ATTR_SAMPLING_FREQUENCY) {
			LOG_WRN("Invalid attribute %d", attr);
			return -EINVAL;
		}
		akm09918c_reg_to_hz(data->mode, val);
		break;
	default:
		LOG_WRN("Invalid channel %d", chan);
		return -EINVAL;
	}
	return 0;
}

static int akm09918c_attr_set(const struct device *dev, enum sensor_channel chan,
			      enum sensor_attribute attr, const struct sensor_value *val)
{
	const struct akm09918c_config *cfg = dev->config;
	struct akm09918c_data *data = dev->data;
	int res;

	switch (chan) {
	case SENSOR_CHAN_MAGN_X:
	case SENSOR_CHAN_MAGN_Y:
	case SENSOR_CHAN_MAGN_Z:
	case SENSOR_CHAN_MAGN_XYZ:
		if (attr != SENSOR_ATTR_SAMPLING_FREQUENCY) {
			LOG_WRN("Invalid attribute %d", attr);
			return -EINVAL;
		}

		uint8_t mode = akm09918c_hz_to_reg(val);

		res = i2c_reg_write_byte_dt(&cfg->i2c, AKM09918C_REG_CNTL2, mode);
		if (res != 0) {
			LOG_ERR("Failed to set sample frequency");
			return -EIO;
		}
		data->mode = mode;
		break;
	default:
		LOG_WRN("Invalid channel %d", chan);
		return -EINVAL;
	}

	return 0;
}

static const struct sensor_driver_api akm09918c_driver_api = {
	.sample_fetch = akm09918c_sample_fetch,
	.channel_get = akm09918c_channel_get,
	.attr_get = akm09918c_attr_get,
	.attr_set = akm09918c_attr_set,
};

static inline int akm09918c_check_who_am_i(const struct i2c_dt_spec *i2c)
{
	uint8_t buffer[2];
	int rc;

	rc = i2c_burst_read_dt(i2c, AKM09918C_REG_WIA1, buffer, ARRAY_SIZE(buffer));
	if (rc != 0) {
		LOG_ERR("Failed to read who-am-i register (rc=%d)", rc);
		return -EIO;
	}

	if (buffer[0] != AKM09918C_WIA1 || buffer[1] != AKM09918C_WIA2) {
		LOG_ERR("Wrong who-am-i value");
		return -EINVAL;
	}

	return 0;
}

static int akm09918c_init(const struct device *dev)
{
	const struct akm09918c_config *cfg = dev->config;
	struct akm09918c_data *data = dev->data;
	int rc;

	if (!i2c_is_ready_dt(&cfg->i2c)) {
		LOG_ERR("I2C bus device not ready");
		return -ENODEV;
	}

	/* Soft reset the chip */
	rc = i2c_reg_write_byte_dt(&cfg->i2c, AKM09918C_REG_CNTL3,
				   FIELD_PREP(AKM09918C_CNTL3_SRST, 1));
	if (rc != 0) {
		LOG_ERR("Failed to soft reset");
		return -EIO;
	}

	/* check chip ID */
	rc = akm09918c_check_who_am_i(&cfg->i2c);
	if (rc != 0) {
		return rc;
	}
	data->mode = AKM09918C_CNTL2_PWR_DOWN;

	return 0;
}

#define AKM09918C_DEFINE(inst)                                                                     \
	static struct akm09918c_data akm09918c_data_##inst;                                        \
                                                                                                   \
	static const struct akm09918c_config akm09918c_config_##inst = {                           \
		.i2c = I2C_DT_SPEC_INST_GET(inst),                                                 \
	};                                                                                         \
                                                                                                   \
	SENSOR_DEVICE_DT_INST_DEFINE(inst, akm09918c_init, NULL, &akm09918c_data_##inst,           \
				     &akm09918c_config_##inst, POST_KERNEL,                        \
				     CONFIG_SENSOR_INIT_PRIORITY, &akm09918c_driver_api);

DT_INST_FOREACH_STATUS_OKAY(AKM09918C_DEFINE)
