zephyr/drivers/reset/reset_intel_socfpga.c
Girisha Dengi 6639756fae drivers: reset: Add reset controller for Intel Agilex5 platform
This is Intel's proprietary IP which controls individual module
reset signals. During each system driver initialization, these
reset signals will be used to bring module out of reset state.

Signed-off-by: Navinkumar Balabakthan <navinkumar.balabakthan@intel.com>
Signed-off-by: Girisha Dengi <girisha.dengi@intel.com>
2023-07-25 16:58:01 +00:00

116 lines
3.1 KiB
C

/*
* Copyright (c) 2022-2023, Intel Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT intel_socfpga_reset
#include <zephyr/device.h>
#include <zephyr/drivers/reset.h>
#include <zephyr/kernel.h>
/** regwidth 4 for 32 bit register */
#define RESET_REG_WIDTH 4
struct reset_intel_config {
DEVICE_MMIO_ROM;
/* check peripheral active low / active high */
bool active_low;
};
struct reset_intel_soc_data {
DEVICE_MMIO_RAM;
};
static int32_t reset_intel_soc_status(const struct device *dev, uint32_t id, uint8_t *status)
{
const struct reset_intel_config *config = (const struct reset_intel_config *)dev->config;
uintptr_t base_address = DEVICE_MMIO_GET(dev);
uint32_t value;
uint16_t offset;
uint8_t regbit;
regbit = (id & ((RESET_REG_WIDTH << (RESET_REG_WIDTH - 1)) - 1));
offset = (id >> (RESET_REG_WIDTH + 1)) << (RESET_REG_WIDTH >> 1);
value = sys_read32(base_address + offset);
*status = !(value & BIT(regbit)) ^ config->active_low;
return 0;
}
static void reset_intel_soc_update(const struct device *dev, uint32_t id, bool assert)
{
const struct reset_intel_config *config = (const struct reset_intel_config *)dev->config;
uintptr_t base_address = DEVICE_MMIO_GET(dev);
uint16_t offset;
uint8_t regbit;
regbit = (id & ((RESET_REG_WIDTH << (RESET_REG_WIDTH - 1)) - 1));
offset = (id >> (RESET_REG_WIDTH + 1)) << (RESET_REG_WIDTH >> 1);
if (assert ^ !config->active_low) {
if (sys_test_bit(base_address + offset, regbit) == 0) {
sys_set_bit(base_address + offset, regbit);
}
} else {
if (sys_test_bit(base_address + offset, regbit) != 0) {
sys_clear_bit(base_address + offset, regbit);
}
}
}
static int32_t reset_intel_soc_line_assert(const struct device *dev, uint32_t id)
{
reset_intel_soc_update(dev, id, true);
return 0;
}
static int32_t reset_intel_soc_line_deassert(const struct device *dev, uint32_t id)
{
reset_intel_soc_update(dev, id, false);
return 0;
}
static int32_t reset_intel_soc_line_toggle(const struct device *dev, uint32_t id)
{
(void)reset_intel_soc_line_assert(dev, id);
/* TODO: Add required delay once tested on Emulator/Hardware platform. */
(void)reset_intel_soc_line_deassert(dev, id);
return 0;
}
static int32_t reset_intel_soc_init(const struct device *dev)
{
DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE);
return 0;
}
static const struct reset_driver_api reset_intel_soc_driver_api = {
.status = reset_intel_soc_status,
.line_assert = reset_intel_soc_line_assert,
.line_deassert = reset_intel_soc_line_deassert,
.line_toggle = reset_intel_soc_line_toggle,
};
#define INTEL_SOC_RESET_INIT(_inst) \
static struct reset_intel_soc_data reset_intel_soc_data_##_inst; \
static const struct reset_intel_config reset_intel_config_##_inst = { \
DEVICE_MMIO_ROM_INIT(DT_DRV_INST(_inst)), \
.active_low = DT_INST_PROP(_inst, active_low), \
}; \
\
DEVICE_DT_INST_DEFINE(_inst, \
reset_intel_soc_init, \
NULL, \
&reset_intel_soc_data_##_inst, \
&reset_intel_config_##_inst, \
PRE_KERNEL_1, \
CONFIG_RESET_INIT_PRIORITY, \
&reset_intel_soc_driver_api);
DT_INST_FOREACH_STATUS_OKAY(INTEL_SOC_RESET_INIT);