/*
 * Copyright (c) 2022 Andrei-Edward Popa
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#define DT_DRV_COMPAT raspberrypi_pico_reset

#include <device.h>
#include <drivers/reset.h>

struct reset_rpi_config {
	DEVICE_MMIO_ROM;
	uint8_t reg_width;
	uint8_t active_low;
	uintptr_t base_address;
};

static int reset_rpi_read_register(const struct device *dev, uint16_t offset, uint32_t *value)
{
	const struct reset_rpi_config *config = dev->config;
	uint32_t base_address = config->base_address;

	switch (config->reg_width) {
	case 1:
		*value = sys_read8(base_address + offset);
		break;
	case 2:
		*value = sys_read16(base_address + offset);
		break;
	case 4:
		*value = sys_read32(base_address + offset);
		break;
	default:
		return -EINVAL;
	}

	return 0;
}

static int reset_rpi_write_register(const struct device *dev, uint16_t offset, uint32_t value)
{
	const struct reset_rpi_config *config = dev->config;
	uint32_t base_address = config->base_address;

	switch (config->reg_width) {
	case 1:
		sys_write8(value, base_address + offset);
		break;
	case 2:
		sys_write16(value, base_address + offset);
		break;
	case 4:
		sys_write32(value, base_address + offset);
		break;
	default:
		return -EINVAL;
	}

	return 0;
}

static int reset_rpi_status(const struct device *dev, uint32_t id, uint8_t *status)
{
	const struct reset_rpi_config *config = dev->config;
	uint16_t offset;
	uint32_t value;
	uint8_t regbit;
	int ret;

	offset = id / (config->reg_width * CHAR_BIT);
	regbit = id % (config->reg_width * CHAR_BIT);

	ret = reset_rpi_read_register(dev, offset, &value);
	if (ret) {
		return ret;
	}

	*status = !(value & BIT(regbit)) ^ !config->active_low;

	return ret;
}

static int reset_rpi_update(const struct device *dev, uint32_t id, uint8_t assert)
{
	const struct reset_rpi_config *config = dev->config;
	uint16_t offset;
	uint32_t value;
	uint8_t regbit;
	int ret;

	offset = id / (config->reg_width * CHAR_BIT);
	regbit = id % (config->reg_width * CHAR_BIT);

	ret = reset_rpi_read_register(dev, offset, &value);
	if (ret) {
		return ret;
	}

	if (assert ^ config->active_low) {
		value |= BIT(regbit);
	} else {
		value &= ~BIT(regbit);
	}

	return reset_rpi_write_register(dev, offset, value);
}

static int reset_rpi_assert(const struct device *dev, uint32_t id)
{
	return reset_rpi_update(dev, id, 1);
}

static int reset_rpi_deassert(const struct device *dev, uint32_t id)
{
	return reset_rpi_update(dev, id, 0);
}

static int reset_rpi_toggle(const struct device *dev, uint32_t id)
{
	int ret;

	ret = reset_rpi_assert(dev, id);
	if (ret) {
		return ret;
	}

	return reset_rpi_deassert(dev, id);
}

static int reset_rpi_init(const struct device *dev)
{
	DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE);

	return 0;
}

static const struct reset_driver_api reset_rpi_driver_api = {
	.status = reset_rpi_status,
	.assert = reset_rpi_assert,
	.deassert = reset_rpi_deassert,
	.toggle = reset_rpi_toggle,
};

#define RPI_RESET_INIT(idx)							\
	static const struct reset_rpi_config reset_rpi_config_##idx = {		\
		DEVICE_MMIO_ROM_INIT(DT_DRV_INST(idx)),				\
		.reg_width = DT_INST_PROP_OR(idx, reg_width, 4),		\
		.active_low = DT_INST_PROP_OR(idx, active_low, 0),		\
		.base_address = DT_INST_REG_ADDR(idx),				\
	};									\
										\
	DEVICE_DT_INST_DEFINE(idx, reset_rpi_init,				\
			      NULL, NULL,					\
			      &reset_rpi_config_##idx, PRE_KERNEL_1,		\
			      CONFIG_RESET_INIT_PRIORITY,			\
			      &reset_rpi_driver_api);

DT_INST_FOREACH_STATUS_OKAY(RPI_RESET_INIT);
