116 lines
3.1 KiB
C
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);
|