/* * Copyright (c) 2022 Andes Technology Corporation. * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include #include /* * SMU(System Management Unit) Registers for hwinfo driver */ /* Register offset*/ #define SMU_SYSTEMVER 0x00 #define SMU_WRSR 0x10 /* Wake-Up and Reset Status Register bitmask */ #define SMU_WRSR_APOR BIT(0) #define SMU_WRSR_MPOR BIT(1) #define SMU_WRSR_HW BIT(2) #define SMU_WRSR_WDT BIT(3) #define SMU_WRSR_SW BIT(4) #define ANDES_RESET_STATUS_MASK BIT_MASK(5) static const struct device *const syscon_dev = DEVICE_DT_GET(DT_NODELABEL(syscon)); ssize_t z_impl_hwinfo_get_device_id(uint8_t *buffer, size_t length) { int ret = 0; uint8_t id[3]; uint32_t ver; if (!device_is_ready(syscon_dev)) { return -ENODEV; } ret = syscon_read_reg(syscon_dev, SMU_SYSTEMVER, &ver); if (ret < 0) { return ret; } if (length > sizeof(id)) { length = sizeof(id); } sys_put_le24(ver, id); memcpy(buffer, id, length); return length; } int z_impl_hwinfo_get_reset_cause(uint32_t *cause) { int ret = 0; uint32_t reason, flags = 0; if (!device_is_ready(syscon_dev)) { return -ENODEV; } ret = syscon_read_reg(syscon_dev, SMU_WRSR, &reason); if (ret < 0) { return ret; } if (reason & SMU_WRSR_APOR) { flags |= RESET_POR; } if (reason & SMU_WRSR_MPOR) { flags |= RESET_POR; } if (reason & SMU_WRSR_HW) { flags |= RESET_PIN; } if (reason & SMU_WRSR_WDT) { flags |= RESET_WATCHDOG; } if (reason & SMU_WRSR_SW) { flags |= RESET_SOFTWARE; } *cause = flags; return 0; } int z_impl_hwinfo_clear_reset_cause(void) { int ret = 0; uint32_t reason; if (!device_is_ready(syscon_dev)) { return -ENODEV; } ret = syscon_write_reg(syscon_dev, SMU_WRSR, ANDES_RESET_STATUS_MASK); if (ret < 0) { return ret; } do { ret = syscon_read_reg(syscon_dev, SMU_WRSR, &reason); } while ((reason & ANDES_RESET_STATUS_MASK) && (!ret)); return ret; } int z_impl_hwinfo_get_supported_reset_cause(uint32_t *supported) { *supported = (RESET_PIN | RESET_WATCHDOG | RESET_SOFTWARE | RESET_POR); return 0; }