/* * Copyright (c) 2022-2023, Intel Corporation. * * SPDX-License-Identifier: Apache-2.0 */ #define DT_DRV_COMPAT intel_socfpga_reset #include #include #include /** 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);