From 0b3a467cbb79ccd2b6d3013b957a77be18e97be3 Mon Sep 17 00:00:00 2001 From: Justin Hammond Date: Sun, 16 Aug 2026 01:45:45 +0800 Subject: [PATCH 1/4] arch/risc-v/eic7700x: Add the CRG reset controller. The Clock and Reset Generator holds the reset line for every block on the SoC. This registers all 324 of them with the NuttX reset framework as a provider implementing assert, deassert, reset and status. A line is addressed as its control register index times thirty two plus its bit, across 61 registers, so the ids are sparse in a space of 1952 and decoding one is arithmetic rather than a lookup. Each register carries three masks over the same bits: which bits are lines at all, which the hardware will not let software drive, and which would take down the system that asserted them. The last are still registered and can be read and released; only assert and reset refuse them. Where each line falls, and why, is recorded beside the table. The lines are active low, which the manual never states. It is inferred from the field naming, the reset defaults and both vendor Linux drivers. If that inference is wrong then deassert asserts, so the evidence for it is written out in full rather than left as a convention. Several lines are absent from the manual, the GPIO resets at offset 0x438 among them. They were recovered from the vendor device tree and confirmed by asserting each one and watching the block stop responding. Registration writes nothing to the hardware. Assisted-by: Claude:claude-opus-5 Signed-off-by: Justin Hammond --- arch/risc-v/include/eic7700x/eic7700x_reset.h | 624 ++++++++++++++++++ arch/risc-v/src/eic7700x/Kconfig | 15 +- arch/risc-v/src/eic7700x/Make.defs | 4 + arch/risc-v/src/eic7700x/eic7700x_reset.c | 282 ++++++++ arch/risc-v/src/eic7700x/eic7700x_reset.h | 118 ++++ arch/risc-v/src/eic7700x/eic7700x_reset_ops.c | 290 ++++++++ arch/risc-v/src/eic7700x/eic7700x_start.c | 12 + .../src/eic7700x/hardware/eic7700x_reset.h | 131 ++++ 8 files changed, 1475 insertions(+), 1 deletion(-) create mode 100644 arch/risc-v/include/eic7700x/eic7700x_reset.h create mode 100644 arch/risc-v/src/eic7700x/eic7700x_reset.c create mode 100644 arch/risc-v/src/eic7700x/eic7700x_reset.h create mode 100644 arch/risc-v/src/eic7700x/eic7700x_reset_ops.c create mode 100644 arch/risc-v/src/eic7700x/hardware/eic7700x_reset.h diff --git a/arch/risc-v/include/eic7700x/eic7700x_reset.h b/arch/risc-v/include/eic7700x/eic7700x_reset.h new file mode 100644 index 0000000000000..22cb25a1c2f06 --- /dev/null +++ b/arch/risc-v/include/eic7700x/eic7700x_reset.h @@ -0,0 +1,624 @@ +/**************************************************************************** + * arch/risc-v/include/eic7700x/eic7700x_reset.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_INCLUDE_EIC7700X_EIC7700X_RESET_H +#define __ARCH_RISCV_INCLUDE_EIC7700X_EIC7700X_RESET_H + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Name this provider registers under. Pass it to reset_control_get() and + * the wrappers around it, together with one of the line ids below. + */ + +#define EIC7700X_RESET_CONTROLLER "eic7700x-crg" + +/* A reset line is named by the control register that holds it and by the + * bit within that register: + * + * id = register index * 32 + bit + * + * The register index is the word offset from the first reset control + * register, so decoding an id is arithmetic and needs no table. Register + * index 0 is offset 0x400 and register index 60 is offset 0x4f0. + */ + +#define EIC7700X_RESET_NREGS 61 +#define EIC7700X_RESET_ID(r, b) ((r) * 32 + (b)) +#define EIC7700X_RESET_REGOF(id) ((id) >> 5) +#define EIC7700X_RESET_BITOF(id) ((id) & 31) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Every reset line the Clock and Reset Generator carries. + * + * The lines are active low: a line is held in reset while its bit reads + * zero and released while it reads one. The manual never says so. It is + * inferred from the field names, which all end in _rstn, _arstn, _prstn or + * _hrstn, from the reset defaults, which read one for every block that has + * to be running before software starts and zero for every block software + * has to bring up, and from both vendor Linux drivers, which assert by + * clearing the bit and deassert by setting it. Before trusting a write, + * read the console UART line back: it must report deasserted on a board + * that is printing. + * + * Section 3.1 of the manual asks that the clock be running before a reset + * is released, and that a block's configuration interface be released + * before its bus interface and core logic. It also warns that resetting a + * block that is not idle can hang the bus. None of that is something this + * provider can enforce; all of it is the caller's to get right. + * + * Lines that carry the fabric, main memory, the cluster NuttX runs on or + * the configuration path back to this register block are registered but + * refuse to be asserted, because asserting one of them takes down the + * system doing the asserting. They can still be released and read. + */ + +enum eic7700x_reset_e +{ + /* 0x400 snoc_rst_ctrl, system network on chip (TRM p141). Every line + * here carries instruction fetch, data, or the path to the generator's + * own registers, so none of them may be asserted. + */ + + EIC7700X_RESET_NOC_NSP = EIC7700X_RESET_ID(0x00, 0), + EIC7700X_RESET_NOC_CFG = EIC7700X_RESET_ID(0x00, 1), + EIC7700X_RESET_RNOC_NSP = EIC7700X_RESET_ID(0x00, 2), + EIC7700X_RESET_SNOC_TCU_A = EIC7700X_RESET_ID(0x00, 3), + EIC7700X_RESET_SNOC_U84_A = EIC7700X_RESET_ID(0x00, 4), + EIC7700X_RESET_SNOC_PCIET_XS = EIC7700X_RESET_ID(0x00, 5), + EIC7700X_RESET_SNOC_PCIET_XM = EIC7700X_RESET_ID(0x00, 6), + EIC7700X_RESET_SNOC_PCIET_P = EIC7700X_RESET_ID(0x00, 7), + EIC7700X_RESET_SNOC_NPU_A = EIC7700X_RESET_ID(0x00, 8), + EIC7700X_RESET_SNOC_JTAG_P = EIC7700X_RESET_ID(0x00, 9), + EIC7700X_RESET_SNOC_DSPT_A = EIC7700X_RESET_ID(0x00, 10), + EIC7700X_RESET_SNOC_DDRC1_P2_A = EIC7700X_RESET_ID(0x00, 11), + EIC7700X_RESET_SNOC_DDRC1_P1_A = EIC7700X_RESET_ID(0x00, 12), + EIC7700X_RESET_SNOC_DDRC0_P2_A = EIC7700X_RESET_ID(0x00, 13), + EIC7700X_RESET_SNOC_DDRC0_P1_A = EIC7700X_RESET_ID(0x00, 14), + EIC7700X_RESET_SNOC_D2D_A = EIC7700X_RESET_ID(0x00, 15), + EIC7700X_RESET_SNOC_AON_A = EIC7700X_RESET_ID(0x00, 16), + + /* 0x404 gpu_rst_ctrl, 3D graphics (TRM p142) */ + + EIC7700X_RESET_GPU_AXI = EIC7700X_RESET_ID(0x01, 0), + EIC7700X_RESET_GPU_CFG = EIC7700X_RESET_ID(0x01, 1), + EIC7700X_RESET_GPU_GRAY = EIC7700X_RESET_ID(0x01, 2), + EIC7700X_RESET_GPU_JONES = EIC7700X_RESET_ID(0x01, 3), + EIC7700X_RESET_GPU_SPU = EIC7700X_RESET_ID(0x01, 4), + + /* 0x408 dsp_rst_ctrl, digital signal processors (TRM p143). The four + * divider resets in sw_dsp_div_rstn[7:4] carry no instance mapping; + * ascending order is assumed. Bit 3 is reserved. + */ + + EIC7700X_RESET_DSP_AXI = EIC7700X_RESET_ID(0x02, 0), + EIC7700X_RESET_DSP_CFG = EIC7700X_RESET_ID(0x02, 1), + EIC7700X_RESET_DSP_DIV4 = EIC7700X_RESET_ID(0x02, 2), + EIC7700X_RESET_DSP_DIV0 = EIC7700X_RESET_ID(0x02, 4), + EIC7700X_RESET_DSP_DIV1 = EIC7700X_RESET_ID(0x02, 5), + EIC7700X_RESET_DSP_DIV2 = EIC7700X_RESET_ID(0x02, 6), + EIC7700X_RESET_DSP_DIV3 = EIC7700X_RESET_ID(0x02, 7), + + /* 0x40c d2d_rst_ctrl, die to die interface (TRM p143). Only the + * subsystem line resets released; the rest come up held. + */ + + EIC7700X_RESET_D2D_AXI = EIC7700X_RESET_ID(0x03, 0), + EIC7700X_RESET_D2D_CFG = EIC7700X_RESET_ID(0x03, 1), + EIC7700X_RESET_D2D_P = EIC7700X_RESET_ID(0x03, 2), + EIC7700X_RESET_D2D_RAW_PCS = EIC7700X_RESET_ID(0x03, 3), + EIC7700X_RESET_D2D_RX = EIC7700X_RESET_ID(0x03, 4), + EIC7700X_RESET_D2D_TX = EIC7700X_RESET_ID(0x03, 5), + EIC7700X_RESET_D2D_CORE = EIC7700X_RESET_ID(0x03, 6), + EIC7700X_RESET_D2D_SUBSYS = EIC7700X_RESET_ID(0x03, 7), + + /* 0x410 ddr_rst_ctrl, both memory controllers (TRM p143). This is the + * memory NuttX runs from, so none of it may be asserted. The manual + * gives no mapping from bit to port for sw_ddr0_p_arstn[20:16] or + * sw_ddr1_p_arstn[4:0]; ascending order is assumed. Note the two + * controllers are not laid out symmetrically. + */ + + EIC7700X_RESET_DDR1_P0_A = EIC7700X_RESET_ID(0x04, 0), + EIC7700X_RESET_DDR1_P1_A = EIC7700X_RESET_ID(0x04, 1), + EIC7700X_RESET_DDR1_P2_A = EIC7700X_RESET_ID(0x04, 2), + EIC7700X_RESET_DDR1_P3_A = EIC7700X_RESET_ID(0x04, 3), + EIC7700X_RESET_DDR1_P4_A = EIC7700X_RESET_ID(0x04, 4), + EIC7700X_RESET_DDR1_TRACE_A = EIC7700X_RESET_ID(0x04, 6), + EIC7700X_RESET_DDR1_PMP_SOFT = EIC7700X_RESET_ID(0x04, 8), + EIC7700X_RESET_DDR0_P0_A = EIC7700X_RESET_ID(0x04, 16), + EIC7700X_RESET_DDR0_P1_A = EIC7700X_RESET_ID(0x04, 17), + EIC7700X_RESET_DDR0_P2_A = EIC7700X_RESET_ID(0x04, 18), + EIC7700X_RESET_DDR0_P3_A = EIC7700X_RESET_ID(0x04, 19), + EIC7700X_RESET_DDR0_P4_A = EIC7700X_RESET_ID(0x04, 20), + EIC7700X_RESET_DDR_CFG = EIC7700X_RESET_ID(0x04, 21), + EIC7700X_RESET_DDR0_TRACE_A = EIC7700X_RESET_ID(0x04, 22), + EIC7700X_RESET_DDR_CORE = EIC7700X_RESET_ID(0x04, 23), + EIC7700X_RESET_DDR0_PMP_SOFT = EIC7700X_RESET_ID(0x04, 24), + EIC7700X_RESET_DDR_P = EIC7700X_RESET_ID(0x04, 26), + + /* 0x414 tcu_rst_ctrl, translation control unit (TRM p144). The manual + * describes tbu_rstn[20:4] only as "Reserved.", giving no mapping from + * bit to translation buffer unit; the seventeen lines below assume the + * ascending order the vendor Linux binding uses. + */ + + EIC7700X_RESET_TCU_AXI = EIC7700X_RESET_ID(0x05, 0), + EIC7700X_RESET_TCU_CFG = EIC7700X_RESET_ID(0x05, 1), + EIC7700X_RESET_TCU_TBU0 = EIC7700X_RESET_ID(0x05, 4), + EIC7700X_RESET_TCU_TBU1 = EIC7700X_RESET_ID(0x05, 5), + EIC7700X_RESET_TCU_TBU2 = EIC7700X_RESET_ID(0x05, 6), + EIC7700X_RESET_TCU_TBU3 = EIC7700X_RESET_ID(0x05, 7), + EIC7700X_RESET_TCU_TBU4 = EIC7700X_RESET_ID(0x05, 8), + EIC7700X_RESET_TCU_TBU5 = EIC7700X_RESET_ID(0x05, 9), + EIC7700X_RESET_TCU_TBU6 = EIC7700X_RESET_ID(0x05, 10), + EIC7700X_RESET_TCU_TBU7 = EIC7700X_RESET_ID(0x05, 11), + EIC7700X_RESET_TCU_TBU8 = EIC7700X_RESET_ID(0x05, 12), + EIC7700X_RESET_TCU_TBU9 = EIC7700X_RESET_ID(0x05, 13), + EIC7700X_RESET_TCU_TBU10 = EIC7700X_RESET_ID(0x05, 14), + EIC7700X_RESET_TCU_TBU11 = EIC7700X_RESET_ID(0x05, 15), + EIC7700X_RESET_TCU_TBU12 = EIC7700X_RESET_ID(0x05, 16), + EIC7700X_RESET_TCU_TBU13 = EIC7700X_RESET_ID(0x05, 17), + EIC7700X_RESET_TCU_TBU14 = EIC7700X_RESET_ID(0x05, 18), + EIC7700X_RESET_TCU_TBU15 = EIC7700X_RESET_ID(0x05, 19), + EIC7700X_RESET_TCU_TBU16 = EIC7700X_RESET_ID(0x05, 20), + + /* 0x418 npu_rst_ctrl, the neural processor (TRM p144). The manual + * marks the two E31 debug and bus lines "reserved" but still names + * them, so they are exposed under their own names. + */ + + EIC7700X_RESET_NPU_AXI = EIC7700X_RESET_ID(0x06, 0), + EIC7700X_RESET_NPU_CFG = EIC7700X_RESET_ID(0x06, 1), + EIC7700X_RESET_NPU_CORE = EIC7700X_RESET_ID(0x06, 2), + EIC7700X_RESET_NPU_E31CORE = EIC7700X_RESET_ID(0x06, 3), + EIC7700X_RESET_NPU_E31BUS = EIC7700X_RESET_ID(0x06, 4), + EIC7700X_RESET_NPU_E31DBG = EIC7700X_RESET_ID(0x06, 5), + EIC7700X_RESET_NPU_LLC = EIC7700X_RESET_ID(0x06, 6), + + /* 0x41c hspdma_rst_ctrl, the high speed peripherals (TRM p145). There + * is no separate register for SD, eMMC or ethernet: everything lives + * here, and every bit resets HELD, so any of these blocks needs its + * lines released before it will answer. + * + * Section 3.1 of the manual asks for the configuration interface first, + * so release HSP_CFG before HSP_AXI and before any of the per device + * lines. + * + * sw_mshc_phy_rstn[5:3] and sw_mshc_txrx_rstn[8:6] are three bit fields + * with no instance mapping in the manual. Controller n is taken to be + * the n'th bit of each field, matching the vendor Linux binding. Take + * care here: instance 0 is bit 3 and bit 6 rather than bit 0, and the + * neighbouring per device lines run eMMC, SD0, SD1 descending while + * this assumption runs ascending, so the two orders do not agree and + * only silicon can say which is right. + */ + + EIC7700X_RESET_HSP_AXI = EIC7700X_RESET_ID(0x07, 0), + EIC7700X_RESET_HSP_CFG = EIC7700X_RESET_ID(0x07, 1), + EIC7700X_RESET_HSP_POR = EIC7700X_RESET_ID(0x07, 2), + EIC7700X_RESET_MSHC0_PHY = EIC7700X_RESET_ID(0x07, 3), + EIC7700X_RESET_MSHC1_PHY = EIC7700X_RESET_ID(0x07, 4), + EIC7700X_RESET_MSHC2_PHY = EIC7700X_RESET_ID(0x07, 5), + EIC7700X_RESET_MSHC0_TXRX = EIC7700X_RESET_ID(0x07, 6), + EIC7700X_RESET_MSHC1_TXRX = EIC7700X_RESET_ID(0x07, 7), + EIC7700X_RESET_MSHC2_TXRX = EIC7700X_RESET_ID(0x07, 8), + EIC7700X_RESET_SATA_ASIC0 = EIC7700X_RESET_ID(0x07, 9), + EIC7700X_RESET_SATA_OOB = EIC7700X_RESET_ID(0x07, 10), + EIC7700X_RESET_SATA_PMALIVE = EIC7700X_RESET_ID(0x07, 11), + EIC7700X_RESET_SATA_RBC = EIC7700X_RESET_ID(0x07, 12), + EIC7700X_RESET_DMA0 = EIC7700X_RESET_ID(0x07, 13), + EIC7700X_RESET_HSP_DMA0 = EIC7700X_RESET_ID(0x07, 14), + EIC7700X_RESET_USB0_VAUX = EIC7700X_RESET_ID(0x07, 15), + EIC7700X_RESET_USB1_VAUX = EIC7700X_RESET_ID(0x07, 16), + EIC7700X_RESET_HSP_SD1_P = EIC7700X_RESET_ID(0x07, 17), + EIC7700X_RESET_HSP_SD0_P = EIC7700X_RESET_ID(0x07, 18), + EIC7700X_RESET_HSP_EMMC_P = EIC7700X_RESET_ID(0x07, 19), + EIC7700X_RESET_HSP_DMA_P = EIC7700X_RESET_ID(0x07, 20), + EIC7700X_RESET_HSP_SD1_A = EIC7700X_RESET_ID(0x07, 21), + EIC7700X_RESET_HSP_SD0_A = EIC7700X_RESET_ID(0x07, 22), + EIC7700X_RESET_HSP_EMMC_A = EIC7700X_RESET_ID(0x07, 23), + EIC7700X_RESET_HSP_DMA_A = EIC7700X_RESET_ID(0x07, 24), + EIC7700X_RESET_HSP_ETH1_A = EIC7700X_RESET_ID(0x07, 25), + EIC7700X_RESET_HSP_ETH0_A = EIC7700X_RESET_ID(0x07, 26), + EIC7700X_RESET_HSP_SATA_A = EIC7700X_RESET_ID(0x07, 27), + + /* 0x420 pcie_rst_ctrl (TRM p146) */ + + EIC7700X_RESET_PCIE_CFG = EIC7700X_RESET_ID(0x08, 0), + EIC7700X_RESET_PCIE_POWERUP = EIC7700X_RESET_ID(0x08, 1), + EIC7700X_RESET_PCIE_PERST = EIC7700X_RESET_ID(0x08, 2), + + /* 0x424 i2c_rst_ctrl (TRM p146). All ten controllers reset HELD, so a + * driver must release its line before touching the peripheral. The + * manual gives sw_i2c_rst_n[9:0] as one field with no instance mapping; + * bit n is taken to be controller n, which is what the vendor Linux + * binding assumes. + * + * The two single bit registers at 0x494 and 0x498 further down are a + * separate thing that the manual does not relate to this field. + */ + + EIC7700X_RESET_I2C0 = EIC7700X_RESET_ID(0x09, 0), + EIC7700X_RESET_I2C1 = EIC7700X_RESET_ID(0x09, 1), + EIC7700X_RESET_I2C2 = EIC7700X_RESET_ID(0x09, 2), + EIC7700X_RESET_I2C3 = EIC7700X_RESET_ID(0x09, 3), + EIC7700X_RESET_I2C4 = EIC7700X_RESET_ID(0x09, 4), + EIC7700X_RESET_I2C5 = EIC7700X_RESET_ID(0x09, 5), + EIC7700X_RESET_I2C6 = EIC7700X_RESET_ID(0x09, 6), + EIC7700X_RESET_I2C7 = EIC7700X_RESET_ID(0x09, 7), + EIC7700X_RESET_I2C8 = EIC7700X_RESET_ID(0x09, 8), + EIC7700X_RESET_I2C9 = EIC7700X_RESET_ID(0x09, 9), + + /* 0x428 fan_rst_ctrl, 0x42c pvt_rst_ctrl (TRM p146) */ + + EIC7700X_RESET_FAN = EIC7700X_RESET_ID(0x0a, 0), + EIC7700X_RESET_PVT_LSP = EIC7700X_RESET_ID(0x0b, 0), + EIC7700X_RESET_PVT_DDR = EIC7700X_RESET_ID(0x0b, 1), + + /* 0x430 mbox_rst_ctrl (TRM p146). Sixteen mailboxes in one field with + * no instance mapping given; ascending order is assumed. + */ + + EIC7700X_RESET_MBOX0 = EIC7700X_RESET_ID(0x0c, 0), + EIC7700X_RESET_MBOX1 = EIC7700X_RESET_ID(0x0c, 1), + EIC7700X_RESET_MBOX2 = EIC7700X_RESET_ID(0x0c, 2), + EIC7700X_RESET_MBOX3 = EIC7700X_RESET_ID(0x0c, 3), + EIC7700X_RESET_MBOX4 = EIC7700X_RESET_ID(0x0c, 4), + EIC7700X_RESET_MBOX5 = EIC7700X_RESET_ID(0x0c, 5), + EIC7700X_RESET_MBOX6 = EIC7700X_RESET_ID(0x0c, 6), + EIC7700X_RESET_MBOX7 = EIC7700X_RESET_ID(0x0c, 7), + EIC7700X_RESET_MBOX8 = EIC7700X_RESET_ID(0x0c, 8), + EIC7700X_RESET_MBOX9 = EIC7700X_RESET_ID(0x0c, 9), + EIC7700X_RESET_MBOX10 = EIC7700X_RESET_ID(0x0c, 10), + EIC7700X_RESET_MBOX11 = EIC7700X_RESET_ID(0x0c, 11), + EIC7700X_RESET_MBOX12 = EIC7700X_RESET_ID(0x0c, 12), + EIC7700X_RESET_MBOX13 = EIC7700X_RESET_ID(0x0c, 13), + EIC7700X_RESET_MBOX14 = EIC7700X_RESET_ID(0x0c, 14), + EIC7700X_RESET_MBOX15 = EIC7700X_RESET_ID(0x0c, 15), + + /* 0x434 uart_rst_ctrl (TRM p147). sw_uart_rst_n[4:0], same lack of an + * instance mapping as the I2C field. All five reset released. + * + * UART0 is the console on the boards supported so far and is not + * locked: losing the console is recoverable, and a serial driver + * resetting its own port is the ordinary case. + */ + + EIC7700X_RESET_UART0 = EIC7700X_RESET_ID(0x0d, 0), + EIC7700X_RESET_UART1 = EIC7700X_RESET_ID(0x0d, 1), + EIC7700X_RESET_UART2 = EIC7700X_RESET_ID(0x0d, 2), + EIC7700X_RESET_UART3 = EIC7700X_RESET_ID(0x0d, 3), + EIC7700X_RESET_UART4 = EIC7700X_RESET_ID(0x0d, 4), + + /* 0x438, the two GPIO controllers. This register is absent from the + * manual, whose table goes straight from 0x434 to 0x43c, but the + * vendor Linux binding names the gap and the blocks would otherwise + * have no reset at all. The reset default is unknown; nothing reads + * or writes this register at startup, so these lines only reach the + * hardware when a driver asks for them. + */ + + EIC7700X_RESET_GPIO0 = EIC7700X_RESET_ID(0x0e, 0), + EIC7700X_RESET_GPIO1 = EIC7700X_RESET_ID(0x0e, 1), + + /* 0x43c timer_rst_ctrl, the low speed timer block (TRM p147) */ + + EIC7700X_RESET_LSP_TIMER = EIC7700X_RESET_ID(0x0f, 0), + + /* 0x440 ssi_rst_ctrl, the two SPI controllers (TRM p147) */ + + EIC7700X_RESET_SSI0 = EIC7700X_RESET_ID(0x10, 0), + EIC7700X_RESET_SSI1 = EIC7700X_RESET_ID(0x10, 1), + + /* 0x444 wdt_rst_ctrl (TRM p147), four watchdogs, order assumed */ + + EIC7700X_RESET_WDT0 = EIC7700X_RESET_ID(0x11, 0), + EIC7700X_RESET_WDT1 = EIC7700X_RESET_ID(0x11, 1), + EIC7700X_RESET_WDT2 = EIC7700X_RESET_ID(0x11, 2), + EIC7700X_RESET_WDT3 = EIC7700X_RESET_ID(0x11, 3), + + /* 0x448 lsp_cfgrst_ctrl (TRM p147). This is the configuration + * interface reset that section 3.1 of the manual says to release + * before the bus and core logic of anything on the low speed bus. + */ + + EIC7700X_RESET_LSP_CFG = EIC7700X_RESET_ID(0x12, 0), + + /* 0x44c u84_rst_ctrl, the application cluster (TRM p147). These are + * the harts NuttX runs on, so the cluster lines may not be asserted. + * The manual gives no mapping from bit to hart for sw_u84_core_rstn + * [3:0] or sw_u84_trace_rstn[11:8]; ascending order is assumed. + * + * Note also that this provider never writes clr_boot_info at 0x30c + * (TRM p140), the register the vendor Linux driver pokes at probe so + * that cluster resets take effect at all. On a board where the boot + * loader left that flag set, these lines are inert. + */ + + EIC7700X_RESET_U84_CORE0 = EIC7700X_RESET_ID(0x13, 0), + EIC7700X_RESET_U84_CORE1 = EIC7700X_RESET_ID(0x13, 1), + EIC7700X_RESET_U84_CORE2 = EIC7700X_RESET_ID(0x13, 2), + EIC7700X_RESET_U84_CORE3 = EIC7700X_RESET_ID(0x13, 3), + EIC7700X_RESET_U84_BUS = EIC7700X_RESET_ID(0x13, 4), + EIC7700X_RESET_U84_DBG = EIC7700X_RESET_ID(0x13, 5), + EIC7700X_RESET_U84_TRACECOM = EIC7700X_RESET_ID(0x13, 6), + EIC7700X_RESET_U84_TRACE0 = EIC7700X_RESET_ID(0x13, 8), + EIC7700X_RESET_U84_TRACE1 = EIC7700X_RESET_ID(0x13, 9), + EIC7700X_RESET_U84_TRACE2 = EIC7700X_RESET_ID(0x13, 10), + EIC7700X_RESET_U84_TRACE3 = EIC7700X_RESET_ID(0x13, 11), + + /* 0x450 scpu_rst_ctrl, the secure processor (TRM p147). NuttX does not + * run on it and cannot restart the firmware it runs, so these are + * registered but not locked; a caller that asserts one is on its own. + */ + + EIC7700X_RESET_SCPU_CORE = EIC7700X_RESET_ID(0x14, 0), + EIC7700X_RESET_SCPU_BUS = EIC7700X_RESET_ID(0x14, 1), + EIC7700X_RESET_SCPU_DBG = EIC7700X_RESET_ID(0x14, 2), + + /* 0x454 lpcpu_rst_ctrl, the low power processor (TRM p147) */ + + EIC7700X_RESET_LPCPU_CORE = EIC7700X_RESET_ID(0x15, 0), + EIC7700X_RESET_LPCPU_BUS = EIC7700X_RESET_ID(0x15, 1), + EIC7700X_RESET_LPCPU_DBG = EIC7700X_RESET_ID(0x15, 2), + + /* 0x458 to 0x46c, the video codec blocks (TRM p148) */ + + EIC7700X_RESET_VC_CFG = EIC7700X_RESET_ID(0x16, 0), + EIC7700X_RESET_VC_AXI = EIC7700X_RESET_ID(0x16, 1), + EIC7700X_RESET_VC_MONCFG = EIC7700X_RESET_ID(0x16, 2), + EIC7700X_RESET_JD_CFG = EIC7700X_RESET_ID(0x17, 0), + EIC7700X_RESET_JD_AXI = EIC7700X_RESET_ID(0x17, 1), + EIC7700X_RESET_JE_CFG = EIC7700X_RESET_ID(0x18, 0), + EIC7700X_RESET_JE_AXI = EIC7700X_RESET_ID(0x18, 1), + EIC7700X_RESET_VD_CFG = EIC7700X_RESET_ID(0x19, 0), + EIC7700X_RESET_VD_AXI = EIC7700X_RESET_ID(0x19, 1), + EIC7700X_RESET_VE_CFG = EIC7700X_RESET_ID(0x1a, 0), + EIC7700X_RESET_VE_AXI = EIC7700X_RESET_ID(0x1a, 1), + EIC7700X_RESET_G2D_CORE = EIC7700X_RESET_ID(0x1b, 0), + EIC7700X_RESET_G2D_CFG = EIC7700X_RESET_ID(0x1b, 1), + EIC7700X_RESET_G2D_AXI = EIC7700X_RESET_ID(0x1b, 2), + + /* 0x470 to 0x480, video input (TRM p149). The six shutter lines are + * one field with no instance mapping; ascending order is assumed. + */ + + EIC7700X_RESET_VI_AXI = EIC7700X_RESET_ID(0x1c, 0), + EIC7700X_RESET_VI_CFG = EIC7700X_RESET_ID(0x1c, 1), + EIC7700X_RESET_VI_DWE = EIC7700X_RESET_ID(0x1c, 2), + EIC7700X_RESET_VI_DVP = EIC7700X_RESET_ID(0x1d, 0), + EIC7700X_RESET_VI_ISP0 = EIC7700X_RESET_ID(0x1e, 0), + EIC7700X_RESET_VI_ISP1 = EIC7700X_RESET_ID(0x1f, 0), + EIC7700X_RESET_VI_SHUTTER0 = EIC7700X_RESET_ID(0x20, 0), + EIC7700X_RESET_VI_SHUTTER1 = EIC7700X_RESET_ID(0x20, 1), + EIC7700X_RESET_VI_SHUTTER2 = EIC7700X_RESET_ID(0x20, 2), + EIC7700X_RESET_VI_SHUTTER3 = EIC7700X_RESET_ID(0x20, 3), + EIC7700X_RESET_VI_SHUTTER4 = EIC7700X_RESET_ID(0x20, 4), + EIC7700X_RESET_VI_SHUTTER5 = EIC7700X_RESET_ID(0x20, 5), + + /* 0x484 to 0x48c, video output (TRM p149). Bit 2 of the phy register + * is reserved. + */ + + EIC7700X_RESET_VO_MIPI_P = EIC7700X_RESET_ID(0x21, 0), + EIC7700X_RESET_VO_P = EIC7700X_RESET_ID(0x21, 1), + EIC7700X_RESET_VO_HDMI_P = EIC7700X_RESET_ID(0x21, 3), + EIC7700X_RESET_HDMI_PHYCTRL = EIC7700X_RESET_ID(0x21, 4), + EIC7700X_RESET_VO_HDMI = EIC7700X_RESET_ID(0x21, 5), + EIC7700X_RESET_VO_I2S = EIC7700X_RESET_ID(0x22, 0), + EIC7700X_RESET_VO_I2S_P = EIC7700X_RESET_ID(0x22, 1), + EIC7700X_RESET_VO_AXI = EIC7700X_RESET_ID(0x23, 0), + EIC7700X_RESET_VO_CFG = EIC7700X_RESET_ID(0x23, 1), + EIC7700X_RESET_VO_DC = EIC7700X_RESET_ID(0x23, 2), + EIC7700X_RESET_VO_DC_P = EIC7700X_RESET_ID(0x23, 3), + + /* 0x490 bootspi_rst_ctrl (TRM p150) */ + + EIC7700X_RESET_BOOTSPI_H = EIC7700X_RESET_ID(0x24, 0), + EIC7700X_RESET_BOOTSPI = EIC7700X_RESET_ID(0x24, 1), + + /* 0x494 i2c1_rst_ctrl, 0x498 i2c0_rst_ctrl (TRM p150). Two separate + * single bit APB resets, presumably for the two always on side I2C + * instances. The manual does not say how they relate to the ten bit + * field at 0x424, so both are exposed and neither is assumed to be a + * duplicate of the other. + */ + + EIC7700X_RESET_I2C1_P = EIC7700X_RESET_ID(0x25, 0), + EIC7700X_RESET_I2C0_P = EIC7700X_RESET_ID(0x26, 0), + + /* 0x49c dma1_rst_ctrl (TRM p150) */ + + EIC7700X_RESET_DMA1_A = EIC7700X_RESET_ID(0x27, 0), + EIC7700X_RESET_DMA1_H = EIC7700X_RESET_ID(0x27, 1), + + /* 0x4a0 to 0x4b8, the security and one time programmable blocks + * (TRM p150, p151). All reset released. + */ + + EIC7700X_RESET_FPRT_H = EIC7700X_RESET_ID(0x28, 0), + EIC7700X_RESET_HBLOCK_H = EIC7700X_RESET_ID(0x29, 0), + EIC7700X_RESET_SECSR_H = EIC7700X_RESET_ID(0x2a, 0), + EIC7700X_RESET_OTP_P = EIC7700X_RESET_ID(0x2b, 0), + EIC7700X_RESET_PKA_H = EIC7700X_RESET_ID(0x2c, 0), + EIC7700X_RESET_SPACC = EIC7700X_RESET_ID(0x2d, 0), + EIC7700X_RESET_TRNG_H = EIC7700X_RESET_ID(0x2e, 0), + + /* 0x4c0 to 0x4cc, the four timer blocks (TRM p151). Each has one APB + * reset and eight counter resets with no mapping given; ascending + * order is assumed. Timer 0 resets released, timers 1 to 3 held. + */ + + EIC7700X_RESET_TIMER0_CNT0 = EIC7700X_RESET_ID(0x30, 0), + EIC7700X_RESET_TIMER0_CNT1 = EIC7700X_RESET_ID(0x30, 1), + EIC7700X_RESET_TIMER0_CNT2 = EIC7700X_RESET_ID(0x30, 2), + EIC7700X_RESET_TIMER0_CNT3 = EIC7700X_RESET_ID(0x30, 3), + EIC7700X_RESET_TIMER0_CNT4 = EIC7700X_RESET_ID(0x30, 4), + EIC7700X_RESET_TIMER0_CNT5 = EIC7700X_RESET_ID(0x30, 5), + EIC7700X_RESET_TIMER0_CNT6 = EIC7700X_RESET_ID(0x30, 6), + EIC7700X_RESET_TIMER0_CNT7 = EIC7700X_RESET_ID(0x30, 7), + EIC7700X_RESET_TIMER0_P = EIC7700X_RESET_ID(0x30, 8), + + EIC7700X_RESET_TIMER1_CNT0 = EIC7700X_RESET_ID(0x31, 0), + EIC7700X_RESET_TIMER1_CNT1 = EIC7700X_RESET_ID(0x31, 1), + EIC7700X_RESET_TIMER1_CNT2 = EIC7700X_RESET_ID(0x31, 2), + EIC7700X_RESET_TIMER1_CNT3 = EIC7700X_RESET_ID(0x31, 3), + EIC7700X_RESET_TIMER1_CNT4 = EIC7700X_RESET_ID(0x31, 4), + EIC7700X_RESET_TIMER1_CNT5 = EIC7700X_RESET_ID(0x31, 5), + EIC7700X_RESET_TIMER1_CNT6 = EIC7700X_RESET_ID(0x31, 6), + EIC7700X_RESET_TIMER1_CNT7 = EIC7700X_RESET_ID(0x31, 7), + EIC7700X_RESET_TIMER1_P = EIC7700X_RESET_ID(0x31, 8), + + EIC7700X_RESET_TIMER2_CNT0 = EIC7700X_RESET_ID(0x32, 0), + EIC7700X_RESET_TIMER2_CNT1 = EIC7700X_RESET_ID(0x32, 1), + EIC7700X_RESET_TIMER2_CNT2 = EIC7700X_RESET_ID(0x32, 2), + EIC7700X_RESET_TIMER2_CNT3 = EIC7700X_RESET_ID(0x32, 3), + EIC7700X_RESET_TIMER2_CNT4 = EIC7700X_RESET_ID(0x32, 4), + EIC7700X_RESET_TIMER2_CNT5 = EIC7700X_RESET_ID(0x32, 5), + EIC7700X_RESET_TIMER2_CNT6 = EIC7700X_RESET_ID(0x32, 6), + EIC7700X_RESET_TIMER2_CNT7 = EIC7700X_RESET_ID(0x32, 7), + EIC7700X_RESET_TIMER2_P = EIC7700X_RESET_ID(0x32, 8), + + EIC7700X_RESET_TIMER3_CNT0 = EIC7700X_RESET_ID(0x33, 0), + EIC7700X_RESET_TIMER3_CNT1 = EIC7700X_RESET_ID(0x33, 1), + EIC7700X_RESET_TIMER3_CNT2 = EIC7700X_RESET_ID(0x33, 2), + EIC7700X_RESET_TIMER3_CNT3 = EIC7700X_RESET_ID(0x33, 3), + EIC7700X_RESET_TIMER3_CNT4 = EIC7700X_RESET_ID(0x33, 4), + EIC7700X_RESET_TIMER3_CNT5 = EIC7700X_RESET_ID(0x33, 5), + EIC7700X_RESET_TIMER3_CNT6 = EIC7700X_RESET_ID(0x33, 6), + EIC7700X_RESET_TIMER3_CNT7 = EIC7700X_RESET_ID(0x33, 7), + EIC7700X_RESET_TIMER3_P = EIC7700X_RESET_ID(0x33, 8), + + /* 0x4d0 rtc_rst_ctrl (TRM p151) */ + + EIC7700X_RESET_RTC = EIC7700X_RESET_ID(0x34, 0), + + /* 0x4d4 mnoc_rst_ctrl, memory network on chip (TRM p151) */ + + EIC7700X_RESET_MNOC_SNOC_NSP = EIC7700X_RESET_ID(0x35, 0), + EIC7700X_RESET_MNOC_VC_A = EIC7700X_RESET_ID(0x35, 1), + EIC7700X_RESET_MNOC_CFG = EIC7700X_RESET_ID(0x35, 2), + EIC7700X_RESET_MNOC_HSP_A = EIC7700X_RESET_ID(0x35, 3), + EIC7700X_RESET_MNOC_GPU_A = EIC7700X_RESET_ID(0x35, 4), + EIC7700X_RESET_MNOC_DDRC1_P3_A = EIC7700X_RESET_ID(0x35, 5), + EIC7700X_RESET_MNOC_DDRC0_P3_A = EIC7700X_RESET_ID(0x35, 6), + + /* 0x4d8 rnoc_rst_ctrl, real time network on chip (TRM p152) */ + + EIC7700X_RESET_RNOC_VO_A = EIC7700X_RESET_ID(0x36, 0), + EIC7700X_RESET_RNOC_VI_A = EIC7700X_RESET_ID(0x36, 1), + EIC7700X_RESET_RNOC_SNOC_NSP = EIC7700X_RESET_ID(0x36, 2), + EIC7700X_RESET_RNOC_CFG = EIC7700X_RESET_ID(0x36, 3), + EIC7700X_RESET_RNOC_DDRC1_P4_A = EIC7700X_RESET_ID(0x36, 4), + EIC7700X_RESET_RNOC_DDRC0_P4_A = EIC7700X_RESET_ID(0x36, 5), + + /* 0x4dc cnoc_rst_ctrl, configuration network on chip (TRM p152). Bit + * 13 is the worst single line on the SoC: asserting it removes access + * to every peripheral's configuration space, this register block + * included, so it cannot be undone. + */ + + EIC7700X_RESET_CNOC_VO_CFG = EIC7700X_RESET_ID(0x37, 0), + EIC7700X_RESET_CNOC_VI_CFG = EIC7700X_RESET_ID(0x37, 1), + EIC7700X_RESET_CNOC_VC_CFG = EIC7700X_RESET_ID(0x37, 2), + EIC7700X_RESET_CNOC_TCU_CFG = EIC7700X_RESET_ID(0x37, 3), + EIC7700X_RESET_CNOC_PCIET_CFG = EIC7700X_RESET_ID(0x37, 4), + EIC7700X_RESET_CNOC_NPU_CFG = EIC7700X_RESET_ID(0x37, 5), + EIC7700X_RESET_CNOC_LSP_CFG = EIC7700X_RESET_ID(0x37, 6), + EIC7700X_RESET_CNOC_HSP_CFG = EIC7700X_RESET_ID(0x37, 7), + EIC7700X_RESET_CNOC_GPU_CFG = EIC7700X_RESET_ID(0x37, 8), + EIC7700X_RESET_CNOC_DSPT_CFG = EIC7700X_RESET_ID(0x37, 9), + EIC7700X_RESET_CNOC_DDRT1_CFG = EIC7700X_RESET_ID(0x37, 10), + EIC7700X_RESET_CNOC_DDRT0_CFG = EIC7700X_RESET_ID(0x37, 11), + EIC7700X_RESET_CNOC_D2D_CFG = EIC7700X_RESET_ID(0x37, 12), + EIC7700X_RESET_CNOC_CFG = EIC7700X_RESET_ID(0x37, 13), + EIC7700X_RESET_CNOC_CLMM_CFG = EIC7700X_RESET_ID(0x37, 14), + EIC7700X_RESET_CNOC_AON_CFG = EIC7700X_RESET_ID(0x37, 15), + + /* 0x4e0 lnoc_rst_ctrl, low latency network on chip (TRM p153) */ + + EIC7700X_RESET_LNOC_CFG = EIC7700X_RESET_ID(0x38, 0), + EIC7700X_RESET_LNOC_NPU_LLC_A = EIC7700X_RESET_ID(0x38, 1), + EIC7700X_RESET_LNOC_DDRC1_P0_A = EIC7700X_RESET_ID(0x38, 2), + EIC7700X_RESET_LNOC_DDRC0_P0_A = EIC7700X_RESET_ID(0x38, 3), + + /* 0x4e4 pipe_rst_ctrl, pipeline cells inside the fabric (TRM p153). + * Neither Linux driver models this register. + */ + + EIC7700X_RESET_PIPE_TBU2SNOC = EIC7700X_RESET_ID(0x39, 0), + EIC7700X_RESET_PIPE_TBU2MNOC = EIC7700X_RESET_ID(0x39, 1), + EIC7700X_RESET_PIPE_SNOC2PCIE = EIC7700X_RESET_ID(0x39, 2), + EIC7700X_RESET_PIPE_SNOC2MNOC = EIC7700X_RESET_ID(0x39, 3), + EIC7700X_RESET_PIPE_SNOC2DDR1P1 = EIC7700X_RESET_ID(0x39, 4), + EIC7700X_RESET_PIPE_SNOC2DDR0P1 = EIC7700X_RESET_ID(0x39, 5), + EIC7700X_RESET_PIPE_SNOC2DDR1P2 = EIC7700X_RESET_ID(0x39, 6), + EIC7700X_RESET_PIPE_SNOC2DDR0P2 = EIC7700X_RESET_ID(0x39, 7), + EIC7700X_RESET_PIPE_SNOC2D2D = EIC7700X_RESET_ID(0x39, 8), + EIC7700X_RESET_PIPE_MCPU2SNOC = EIC7700X_RESET_ID(0x39, 9), + EIC7700X_RESET_PIPE_MCPU2SNOCSP = EIC7700X_RESET_ID(0x39, 10), + EIC7700X_RESET_PIPE_MNOC2SNOC = EIC7700X_RESET_ID(0x39, 11), + EIC7700X_RESET_PIPE_LNOC2DDR1 = EIC7700X_RESET_ID(0x39, 12), + EIC7700X_RESET_PIPE_LNOC2DDR0 = EIC7700X_RESET_ID(0x39, 13), + EIC7700X_RESET_PIPE_RNOC2DDR1 = EIC7700X_RESET_ID(0x39, 14), + EIC7700X_RESET_PIPE_RNOC2DDR0 = EIC7700X_RESET_ID(0x39, 15), + EIC7700X_RESET_PIPE_MNOC2DDR0 = EIC7700X_RESET_ID(0x39, 16), + EIC7700X_RESET_PIPE_SNOC2DSP = EIC7700X_RESET_ID(0x39, 17), + EIC7700X_RESET_PIPE_DSP2SNOC = EIC7700X_RESET_ID(0x39, 18), + EIC7700X_RESET_PIPE_DSP2TCU = EIC7700X_RESET_ID(0x39, 19), + EIC7700X_RESET_PIPE_PCIE2TCU = EIC7700X_RESET_ID(0x39, 20), + EIC7700X_RESET_PIPE_VI2RNOC = EIC7700X_RESET_ID(0x39, 21), + EIC7700X_RESET_PIPE_VO2RNOC = EIC7700X_RESET_ID(0x39, 22), + EIC7700X_RESET_PIPE_GPU2MNOC = EIC7700X_RESET_ID(0x39, 23), + EIC7700X_RESET_PIPE_VC2MNOC = EIC7700X_RESET_ID(0x39, 24), + + /* 0x4e8 tbu_rst_ctrl, translation buffer units (TRM p155). Neither + * Linux driver models this register. + */ + + EIC7700X_RESET_TBU_AON_A = EIC7700X_RESET_ID(0x3a, 0), + EIC7700X_RESET_TBU_PCIET_TBU3 = EIC7700X_RESET_ID(0x3a, 1), + EIC7700X_RESET_TBU_HSP_A = EIC7700X_RESET_ID(0x3a, 2), + EIC7700X_RESET_TBU_VI_AXI = EIC7700X_RESET_ID(0x3a, 3), + + /* 0x4ec reset_status (TRM p155). The one read only line in the block: + * it reports the reset state of the far die on a dual die part. Only + * reset_control_status() works on it; the write operations return + * -EROFS. + */ + + EIC7700X_RESET_EXT_D2D_STATUS = EIC7700X_RESET_ID(0x3b, 0), + + /* 0x4f0 test_rst_ctrl (TRM p155). Neither Linux driver models this + * register. + */ + + EIC7700X_RESET_TESTMUX = EIC7700X_RESET_ID(0x3c, 0), + EIC7700X_RESET_SPI_SLV = EIC7700X_RESET_ID(0x3c, 1), +}; + +#endif /* __ARCH_RISCV_INCLUDE_EIC7700X_EIC7700X_RESET_H */ diff --git a/arch/risc-v/src/eic7700x/Kconfig b/arch/risc-v/src/eic7700x/Kconfig index 31cbbc73b206e..c015c8bc5a789 100644 --- a/arch/risc-v/src/eic7700x/Kconfig +++ b/arch/risc-v/src/eic7700x/Kconfig @@ -47,4 +47,17 @@ config EIC7700X_CPU_FREQ_MHZ cores at 1400, so the default changes nothing and merely says so in the log. -endif \ No newline at end of file +endif +config EIC7700X_RESET + bool "CRG reset provider" + default y + select RESET + ---help--- + Register the reset lines of the Clock and Reset Generator (CRG) + with the NuttX reset framework. Registration writes nothing to + the hardware: a line only moves when a driver asks it to. + + Lines that carry the interconnect, the DDR path, the U84 cluster + or the configuration path back to the CRG are registered so that + they can be released and read, but refuse to be asserted, since + asserting one of them takes down the system doing the asserting. diff --git a/arch/risc-v/src/eic7700x/Make.defs b/arch/risc-v/src/eic7700x/Make.defs index 28614bcb7902f..0402ae7c0452c 100644 --- a/arch/risc-v/src/eic7700x/Make.defs +++ b/arch/risc-v/src/eic7700x/Make.defs @@ -39,3 +39,7 @@ endif ifeq ($(CONFIG_EIC7700X_CPUCLK),y) CHIP_CSRCS += eic7700x_cpuclk.c endif + +ifeq ($(CONFIG_EIC7700X_RESET),y) +CHIP_CSRCS += eic7700x_reset.c eic7700x_reset_ops.c +endif diff --git a/arch/risc-v/src/eic7700x/eic7700x_reset.c b/arch/risc-v/src/eic7700x/eic7700x_reset.c new file mode 100644 index 0000000000000..479a3e261558b --- /dev/null +++ b/arch/risc-v/src/eic7700x/eic7700x_reset.c @@ -0,0 +1,282 @@ +/**************************************************************************** + * arch/risc-v/src/eic7700x/eic7700x_reset.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "riscv_internal.h" +#include "eic7700x_reset.h" +#include "hardware/eic7700x_reset.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* One table row. Writing the register index into the designated + * initialiser keeps a row's position in the array visibly equal to the + * register index that a reset line id carries in its upper bits. + */ + +#define RSTREG(i, v, r, c) \ + [i] = \ + { \ + .valid = (v), .rdonly = (r), .critical = (c) \ + } + +/* System critical means a line whose assertion takes down the system that + * is asserting it: the fabric that carries instruction fetch, the memory + * the kernel runs from, the cluster it runs on, the configuration path + * back to this very register block, and the pipeline and translation + * buffer cells inside those paths. Those lines are registered so that a + * driver can still release them and read their state, but assert and + * reset return -EPERM. + * + * The line is drawn at "will hang", not "might upset something". Section + * 3.1 of the manual warns that resetting any block that is not idle can + * hang the bus, which is true of every line in the table and so cannot be + * the criterion here. Defining each critical mask in terms of the + * matching valid mask keeps the two in step by construction. + */ + +#define SNOC_RST_CRIT SNOC_RST_VALID +#define DDR_RST_CRIT DDR_RST_VALID +#define TCU_RST_CRIT TCU_RST_VALID +#define LSPCFG_RST_CRIT LSPCFG_RST_VALID +#define U84_RST_CRIT U84_RST_VALID +#define MNOC_RST_CRIT MNOC_RST_VALID +#define RNOC_RST_CRIT RNOC_RST_VALID +#define CNOC_RST_CRIT CNOC_RST_VALID +#define LNOC_RST_CRIT LNOC_RST_VALID +#define PIPE_RST_CRIT PIPE_RST_VALID +#define TBU_RST_CRIT TBU_RST_VALID + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* The reset controller. The framework does not allocate this and there is + * no per instance state to carry: the register base is a compile time + * constant and everything else falls out of the line id, so a file scope + * object is all that is needed and no container_of is involved. + */ + +static struct reset_controller_dev g_eic7700x_rcdev = +{ + .name = EIC7700X_RESET_CONTROLLER, + .ops = &g_eic7700x_reset_ops, +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* Which bits of each control register name a reset line, which of those + * the hardware will not let software drive, and which of them refuse to be + * asserted. Rows not listed are all zero, so every id in them is + * rejected, which is what the registers this SoC does not have resolve to. + */ + +const struct eic7700x_reset_reg_s +g_eic7700x_reset_regs[EIC7700X_RESET_NREGS] = +{ + RSTREG(0x00, SNOC_RST_VALID, 0, SNOC_RST_CRIT), + RSTREG(0x01, GPU_RST_VALID, 0, 0), + RSTREG(0x02, DSP_RST_VALID, 0, 0), + RSTREG(0x03, D2D_RST_VALID, 0, 0), + RSTREG(0x04, DDR_RST_VALID, 0, DDR_RST_CRIT), + RSTREG(0x05, TCU_RST_VALID, 0, TCU_RST_CRIT), + RSTREG(0x06, NPU_RST_VALID, 0, 0), + RSTREG(0x07, HSPDMA_RST_VALID, 0, 0), + RSTREG(0x08, PCIE_RST_VALID, 0, 0), + RSTREG(0x09, I2C_RST_VALID, 0, 0), + RSTREG(0x0a, FAN_RST_VALID, 0, 0), + RSTREG(0x0b, PVT_RST_VALID, 0, 0), + RSTREG(0x0c, MBOX_RST_VALID, 0, 0), + RSTREG(0x0d, UART_RST_VALID, 0, 0), + RSTREG(0x0e, GPIO_RST_VALID, 0, 0), + RSTREG(0x0f, TIMER_RST_VALID, 0, 0), + RSTREG(0x10, SSI_RST_VALID, 0, 0), + RSTREG(0x11, WDT_RST_VALID, 0, 0), + RSTREG(0x12, LSPCFG_RST_VALID, 0, LSPCFG_RST_CRIT), + RSTREG(0x13, U84_RST_VALID, 0, U84_RST_CRIT), + RSTREG(0x14, SCPU_RST_VALID, 0, 0), + RSTREG(0x15, LPCPU_RST_VALID, 0, 0), + RSTREG(0x16, VC_RST_VALID, 0, 0), + RSTREG(0x17, JD_RST_VALID, 0, 0), + RSTREG(0x18, JE_RST_VALID, 0, 0), + RSTREG(0x19, VD_RST_VALID, 0, 0), + RSTREG(0x1a, VE_RST_VALID, 0, 0), + RSTREG(0x1b, G2D_RST_VALID, 0, 0), + RSTREG(0x1c, VI_RST_VALID, 0, 0), + RSTREG(0x1d, DVP_RST_VALID, 0, 0), + RSTREG(0x1e, ISP0_RST_VALID, 0, 0), + RSTREG(0x1f, ISP1_RST_VALID, 0, 0), + RSTREG(0x20, SHUTTER_RST_VALID, 0, 0), + RSTREG(0x21, VOPHY_RST_VALID, 0, 0), + RSTREG(0x22, VOI2S_RST_VALID, 0, 0), + RSTREG(0x23, VO_RST_VALID, 0, 0), + RSTREG(0x24, BOOTSPI_RST_VALID, 0, 0), + RSTREG(0x25, I2C1_RST_VALID, 0, 0), + RSTREG(0x26, I2C0_RST_VALID, 0, 0), + RSTREG(0x27, DMA1_RST_VALID, 0, 0), + RSTREG(0x28, FPRT_RST_VALID, 0, 0), + RSTREG(0x29, HBLOCK_RST_VALID, 0, 0), + RSTREG(0x2a, SECSR_RST_VALID, 0, 0), + RSTREG(0x2b, OTP_RST_VALID, 0, 0), + RSTREG(0x2c, PKA_RST_VALID, 0, 0), + RSTREG(0x2d, SPACC_RST_VALID, 0, 0), + RSTREG(0x2e, TRNG_RST_VALID, 0, 0), + + /* 0x4bc is reserved. The manual documents nothing at this offset + * and the vendor Linux binding names the index RESERVED, so the row + * is written out explicitly rather than left to the zero fill: any + * id landing in it is rejected, and the gap is visible in the table. + */ + + RSTREG(0x2f, 0, 0, 0), + + RSTREG(0x30, TIMER0_RST_VALID, 0, 0), + RSTREG(0x31, TIMER1_RST_VALID, 0, 0), + RSTREG(0x32, TIMER2_RST_VALID, 0, 0), + RSTREG(0x33, TIMER3_RST_VALID, 0, 0), + RSTREG(0x34, RTC_RST_VALID, 0, 0), + RSTREG(0x35, MNOC_RST_VALID, 0, MNOC_RST_CRIT), + RSTREG(0x36, RNOC_RST_VALID, 0, RNOC_RST_CRIT), + RSTREG(0x37, CNOC_RST_VALID, 0, CNOC_RST_CRIT), + RSTREG(0x38, LNOC_RST_VALID, 0, LNOC_RST_CRIT), + RSTREG(0x39, PIPE_RST_VALID, 0, PIPE_RST_CRIT), + RSTREG(0x3a, TBU_RST_VALID, 0, TBU_RST_CRIT), + RSTREG(0x3b, STATUS_RST_VALID, STATUS_RST_VALID, 0), + RSTREG(0x3c, TEST_RST_VALID, 0, 0), +}; + +/* The table has to describe exactly the id space the public header + * promises, and the last row has to land on the last control register. + */ + +static_assert(nitems(g_eic7700x_reset_regs) == EIC7700X_RESET_NREGS, + "reset table length must match the id space bound"); +static_assert(EIC7700X_RESET_CTRL(EIC7700X_RESET_NREGS - 1) == + EIC7700X_RESET_BASE + 0x00f0, + "the last reset control register is at offset 0x4f0"); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: eic7700x_reset_initialize + * + * Description: + * Register the reset lines of the Clock and Reset Generator with the + * reset framework. See eic7700x_reset.h. + * + ****************************************************************************/ + +/* What eic7700x_reset_initialize() found, for the board to report */ + +static unsigned int g_eic7700x_reset_count; +static unsigned int g_eic7700x_reset_held; + +int eic7700x_reset_initialize(void) +{ + size_t reg; + int ret; + +#ifdef CONFIG_DEBUG_ASSERTIONS + size_t i; + + /* A critical or read only bit that names no line, or a line marked as + * both, means a mistyped mask. Either would show up on hardware as a + * reset that silently does nothing, which is a poor way to find out. + */ + + for (i = 0; i < nitems(g_eic7700x_reset_regs); i++) + { + FAR const struct eic7700x_reset_reg_s *desc = + &g_eic7700x_reset_regs[i]; + + DEBUGASSERT((desc->critical & ~desc->valid) == 0); + DEBUGASSERT((desc->rdonly & ~desc->valid) == 0); + DEBUGASSERT((desc->critical & desc->rdonly) == 0); + } +#endif + + ret = reset_controller_register(&g_eic7700x_rcdev); + if (ret < 0) + { + rsterr("failed to register the reset controller: %d\n", ret); + return ret; + } + + rstinfo("registered %s\n", g_eic7700x_rcdev.name); + + /* Count what the boot loader left, one register read per register + * rather than one per line. The lines are active low, so a valid bit + * reading zero is a line still held. + */ + + for (reg = 0; reg < nitems(g_eic7700x_reset_regs); reg++) + { + uint32_t valid = g_eic7700x_reset_regs[reg].valid; + uint32_t raw = getreg32(EIC7700X_RESET_CTRL(reg)); + + g_eic7700x_reset_count += __builtin_popcount(valid); + g_eic7700x_reset_held += __builtin_popcount(valid & ~raw); + } + + return OK; +} + +/**************************************************************************** + * Name: eic7700x_reset_count + * + * Description: + * What eic7700x_reset_initialize() found. See eic7700x_reset.h. + * + ****************************************************************************/ + +unsigned int eic7700x_reset_count(FAR unsigned int *held) +{ + if (held != NULL) + { + *held = g_eic7700x_reset_held; + } + + return g_eic7700x_reset_count; +} diff --git a/arch/risc-v/src/eic7700x/eic7700x_reset.h b/arch/risc-v/src/eic7700x/eic7700x_reset.h new file mode 100644 index 0000000000000..68c6cc5091a01 --- /dev/null +++ b/arch/risc-v/src/eic7700x/eic7700x_reset.h @@ -0,0 +1,118 @@ +/**************************************************************************** + * arch/risc-v/src/eic7700x/eic7700x_reset.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_EIC7700X_EIC7700X_RESET_H +#define __ARCH_RISCV_SRC_EIC7700X_EIC7700X_RESET_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include + +#include + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* One reset control register, described by three masks over the same + * thirty two bits. + * + * The sets nest: rdonly and critical are both subsets of valid, and they + * do not overlap each other. A line the hardware will not let software + * drive is already unreachable, so marking it critical as well would say + * nothing. eic7700x_reset_initialize() checks all three invariants when + * assertions are enabled. + */ + +struct eic7700x_reset_reg_s +{ + uint32_t valid; /* Bits that name a reset line */ + uint32_t rdonly; /* Valid bits the hardware will not let us drive */ + uint32_t critical; /* Valid bits that refuse assert and reset */ +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +EXTERN const struct reset_control_ops g_eic7700x_reset_ops; +EXTERN const struct eic7700x_reset_reg_s + g_eic7700x_reset_regs[EIC7700X_RESET_NREGS]; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: eic7700x_reset_initialize + * + * Description: + * Register the reset lines of the Clock and Reset Generator with the + * reset framework. Registration writes nothing to the hardware: a line + * only moves when a driver asks it to. + * + * Returned Value: + * OK on success, or a negated errno on failure. + * + ****************************************************************************/ + +int eic7700x_reset_initialize(void); + +/**************************************************************************** + * Name: eic7700x_reset_count + * + * Description: + * How many reset lines the controller has, and how many of them the boot + * loader left held. Both zero before eic7700x_reset_initialize() has + * run. The held figure is the state at that moment and does not track + * what drivers release afterwards. + * + * Input Parameters: + * held - Where to report the number held, or NULL + * + * Returned Value: + * The number of reset lines. + * + ****************************************************************************/ + +unsigned int eic7700x_reset_count(FAR unsigned int *held); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __ARCH_RISCV_SRC_EIC7700X_EIC7700X_RESET_H */ diff --git a/arch/risc-v/src/eic7700x/eic7700x_reset_ops.c b/arch/risc-v/src/eic7700x/eic7700x_reset_ops.c new file mode 100644 index 0000000000000..062a3ea0af2e1 --- /dev/null +++ b/arch/risc-v/src/eic7700x/eic7700x_reset_ops.c @@ -0,0 +1,290 @@ +/**************************************************************************** + * arch/risc-v/src/eic7700x/eic7700x_reset_ops.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include + +#include "riscv_internal.h" +#include "eic7700x_reset.h" +#include "hardware/eic7700x_reset.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* The manual gives no minimum pulse width for a software reset. The + * vendor Linux driver sleeps between ten and fifteen microseconds; a busy + * wait of ten is used here instead so that the reset operation stays + * callable from any context. + */ + +#define EIC7700X_RESET_PULSE_US 10 + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: eic7700x_reset_decode + * + * Description: + * Split a reset line id into the register that holds the line and a + * single bit mask, and confirm that the bit names a line this SoC has. + * + * Nothing in the reset framework bounds an id. reset_control_get() + * rejects a negative index and hands every other value straight through, + * so this is the only place an out of range id is ever caught and every + * one of the operations below has to start here. + * + * Input Parameters: + * id - The reset line id, register index times 32 plus bit + * reg - Receives the address of the control register + * mask - Receives the bit mask within that register + * + * Returned Value: + * The register description, or NULL if the id names no reset line. + * + ****************************************************************************/ + +static FAR const struct eic7700x_reset_reg_s * +eic7700x_reset_decode(unsigned int id, FAR uintptr_t *reg, + FAR uint32_t *mask) +{ + FAR const struct eic7700x_reset_reg_s *desc; + unsigned int index = EIC7700X_RESET_REGOF(id); + uint32_t bit = 1ul << EIC7700X_RESET_BITOF(id); + + if (index >= EIC7700X_RESET_NREGS) + { + rsterr("id %u: register %u is past the end of the block\n", + id, index); + return NULL; + } + + desc = &g_eic7700x_reset_regs[index]; + if ((desc->valid & bit) == 0) + { + rsterr("id %u: no reset line at register %u bit %u\n", + id, index, EIC7700X_RESET_BITOF(id)); + return NULL; + } + + *reg = EIC7700X_RESET_CTRL(index); + *mask = bit; + return desc; +} + +/**************************************************************************** + * Name: eic7700x_reset_status + * + * Description: + * Report whether a reset line is asserted. The lines are active low, so + * a line is in reset while its bit reads zero. + * + * Input Parameters: + * rcdev - The reset controller + * id - The reset line id + * + * Returned Value: + * One if the line is asserted, zero if it is released, or a negated + * errno if the id names no line. + * + ****************************************************************************/ + +static int eic7700x_reset_status(FAR struct reset_controller_dev *rcdev, + unsigned int id) +{ + uintptr_t reg; + uint32_t mask; + + if (eic7700x_reset_decode(id, ®, &mask) == NULL) + { + return -EINVAL; + } + + return (getreg32(reg) & mask) != 0 ? 0 : 1; +} + +/**************************************************************************** + * Name: eic7700x_reset_deassert + * + * Description: + * Bring a line out of reset by setting its bit. Deassert is allowed on + * every line the hardware lets software drive, including the lines that + * refuse to be asserted: releasing a reset can only ever start a block, + * never stop one. + * + * Input Parameters: + * rcdev - The reset controller + * id - The reset line id + * + * Returned Value: + * OK, -EINVAL if the id names no line, or -EROFS if the hardware will + * not let software drive it. + * + ****************************************************************************/ + +static int eic7700x_reset_deassert(FAR struct reset_controller_dev *rcdev, + unsigned int id) +{ + FAR const struct eic7700x_reset_reg_s *desc; + uintptr_t reg; + uint32_t mask; + + desc = eic7700x_reset_decode(id, ®, &mask); + if (desc == NULL) + { + return -EINVAL; + } + + if ((desc->rdonly & mask) != 0) + { + rsterr("id %u: line reports state only, it cannot be driven\n", id); + return -EROFS; + } + + modifyreg32(reg, 0, mask); + return OK; +} + +/**************************************************************************** + * Name: eic7700x_reset_assert + * + * Description: + * Put a line into reset by clearing its bit, unless the line carries + * something the running system cannot lose. See the policy note above + * the table in eic7700x_reset.c for what counts as that. + * + * Input Parameters: + * rcdev - The reset controller + * id - The reset line id + * + * Returned Value: + * OK, -EINVAL if the id names no line, -EROFS if the hardware will not + * let software drive it, or -EPERM if the line is system critical. + * + ****************************************************************************/ + +static int eic7700x_reset_assert(FAR struct reset_controller_dev *rcdev, + unsigned int id) +{ + FAR const struct eic7700x_reset_reg_s *desc; + uintptr_t reg; + uint32_t mask; + + desc = eic7700x_reset_decode(id, ®, &mask); + if (desc == NULL) + { + return -EINVAL; + } + + if ((desc->rdonly & mask) != 0) + { + rsterr("id %u: line reports state only, it cannot be driven\n", id); + return -EROFS; + } + + if ((desc->critical & mask) != 0) + { + rsterr("id %u: refusing to assert a system critical line\n", id); + return -EPERM; + } + + modifyreg32(reg, mask, 0); + return OK; +} + +/**************************************************************************** + * Name: eic7700x_reset_reset + * + * Description: + * Pulse a line: assert, wait, deassert. + * + * The assert goes through eic7700x_reset_assert() rather than being + * done inline so that the id checks and the refusal to touch a system + * critical line live in one place. A line that must not be asserted + * must not be pulsed either, and this way that holds by construction. + * + * The pair is not atomic against a concurrent assert on the same line. + * Each register update is, but the framework does not serialise + * operations and this provider does not add a lock the framework does + * not expect. + * + * Input Parameters: + * rcdev - The reset controller + * id - The reset line id + * + * Returned Value: + * OK, or the error eic7700x_reset_assert() refused the line with; a + * line that may not be asserted may not be pulsed either. + * + ****************************************************************************/ + +static int eic7700x_reset_reset(FAR struct reset_controller_dev *rcdev, + unsigned int id) +{ + int ret; + + ret = eic7700x_reset_assert(rcdev, id); + if (ret < 0) + { + return ret; + } + + up_udelay(EIC7700X_RESET_PULSE_US); + return eic7700x_reset_deassert(rcdev, id); +} + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* The acquire and release operations are deliberately absent. The + * framework only calls them when the rpmsg proxy is built and treats a + * missing one as success, so there is nothing for them to do here. + * + * Naming a member assert in a designated initialiser is safe even though + * assert() is a function like macro: such a macro only expands where the + * identifier is followed by an opening parenthesis, and here it is + * followed by an equals sign. drivers/reset/core.c needs an #undef only + * because it calls through this table. Nothing in this file does, so + * nothing here undefines assert(), which would disable it for the rest of + * the translation unit. + */ + +const struct reset_control_ops g_eic7700x_reset_ops = +{ + .reset = eic7700x_reset_reset, + .assert = eic7700x_reset_assert, + .deassert = eic7700x_reset_deassert, + .status = eic7700x_reset_status, +}; diff --git a/arch/risc-v/src/eic7700x/eic7700x_start.c b/arch/risc-v/src/eic7700x/eic7700x_start.c index b2df89c9b401b..56fa79e5a2fbc 100644 --- a/arch/risc-v/src/eic7700x/eic7700x_start.c +++ b/arch/risc-v/src/eic7700x/eic7700x_start.c @@ -42,6 +42,9 @@ #ifdef CONFIG_EIC7700X_CLK # include "eic7700x_clk.h" #endif +#ifdef CONFIG_EIC7700X_RESET +# include "eic7700x_reset.h" +#endif /**************************************************************************** * Pre-processor Definitions @@ -477,4 +480,13 @@ void weak_function riscv_soc_initialize(void) #ifdef CONFIG_EIC7700X_CLK eic7700x_clk_initialize(); #endif + + /* After the clocks, so that a driver holding both a clock and a reset + * finds them in the order section 3.1 of the manual asks for. Neither + * call touches the hardware; both only publish what is already there. + */ + +#ifdef CONFIG_EIC7700X_RESET + eic7700x_reset_initialize(); +#endif } diff --git a/arch/risc-v/src/eic7700x/hardware/eic7700x_reset.h b/arch/risc-v/src/eic7700x/hardware/eic7700x_reset.h new file mode 100644 index 0000000000000..e798ba118c2e3 --- /dev/null +++ b/arch/risc-v/src/eic7700x/hardware/eic7700x_reset.h @@ -0,0 +1,131 @@ +/**************************************************************************** + * arch/risc-v/src/eic7700x/hardware/eic7700x_reset.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_EIC7700X_HARDWARE_EIC7700X_RESET_H +#define __ARCH_RISCV_SRC_EIC7700X_HARDWARE_EIC7700X_RESET_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "hardware/eic7700x_clk.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register definitions transcribed from the EIC7700X SoC Technical + * Reference Manual v1.0.0, Part 1 section 3.2. Page numbers in the + * comments below are PDF page numbers of Part 1; the printed page number + * is the PDF page number minus 16. + * + * The reset controls are the second half of the Clock and Reset Generator + * whose base is defined alongside the clock registers. Offsets 0x400 to + * 0x4f0 hold one control register per peripheral group (TRM p141 to p155). + * The system control and boot configuration registers at 0x300 to 0x340 + * are deliberately omitted: none of them is a per peripheral reset. + */ + +#define EIC7700X_RESET_BASE (EIC7700X_CLK_BASE + 0x0400) +#define EIC7700X_RESET_CTRL(n) (EIC7700X_RESET_BASE + 4 * (n)) + +/* Bits that name a reset line, one mask per control register. Everything + * else in each word is marked reserved and read only by the manual. + * + * Note that the Default column of the manual disagrees with the MSB and + * LSB columns for 0x49c, 0x4d8 and 0x4ec, stating a width that does not + * match the bit range. These masks follow the bit range, which is the + * self consistent one. + */ + +#define SNOC_RST_VALID 0x0001fffful /* 0x400 p141, 17 lines */ +#define GPU_RST_VALID 0x0000001ful /* 0x404 p142, 5 lines */ +#define DSP_RST_VALID 0x000000f7ul /* 0x408 p143, 7 lines */ +#define D2D_RST_VALID 0x000000fful /* 0x40c p143, 8 lines */ +#define DDR_RST_VALID 0x05ff015ful /* 0x410 p143, 17 lines */ +#define TCU_RST_VALID 0x001ffff3ul /* 0x414 p144, 19 lines */ +#define NPU_RST_VALID 0x0000007ful /* 0x418 p144, 7 lines */ +#define HSPDMA_RST_VALID 0x0ffffffful /* 0x41c p145, 28 lines */ +#define PCIE_RST_VALID 0x00000007ul /* 0x420 p146, 3 lines */ +#define I2C_RST_VALID 0x000003fful /* 0x424 p146, 10 lines */ +#define FAN_RST_VALID 0x00000001ul /* 0x428 p146, 1 line */ +#define PVT_RST_VALID 0x00000003ul /* 0x42c p146, 2 lines */ +#define MBOX_RST_VALID 0x0000fffful /* 0x430 p146, 16 lines */ +#define UART_RST_VALID 0x0000001ful /* 0x434 p147, 5 lines */ + +/* 0x438 is absent from the manual, whose table goes straight from 0x434 + * to 0x43c. The vendor Linux binding names the gap gpio_rst_ctrl with + * one bit per controller, and the SoC has two GPIO blocks that would + * otherwise have no reset at all. The reset default is unknown, so the + * page column below reads as a gap rather than a citation. + */ + +#define GPIO_RST_VALID 0x00000003ul /* 0x438: , 2 lines */ +#define TIMER_RST_VALID 0x00000001ul /* 0x43c p147, 1 line */ +#define SSI_RST_VALID 0x00000003ul /* 0x440 p147, 2 lines */ +#define WDT_RST_VALID 0x0000000ful /* 0x444 p147, 4 lines */ +#define LSPCFG_RST_VALID 0x00000001ul /* 0x448 p147, 1 line */ +#define U84_RST_VALID 0x00000f7ful /* 0x44c p147, 11 lines */ +#define SCPU_RST_VALID 0x00000007ul /* 0x450 p147, 3 lines */ +#define LPCPU_RST_VALID 0x00000007ul /* 0x454 p147, 3 lines */ +#define DMA1_RST_VALID 0x00000003ul /* 0x49c p150, 2 lines */ +#define VC_RST_VALID 0x00000007ul /* 0x458 p148, 3 lines */ +#define JD_RST_VALID 0x00000003ul /* 0x45c p148, 2 lines */ +#define JE_RST_VALID 0x00000003ul /* 0x460 p148, 2 lines */ +#define VD_RST_VALID 0x00000003ul /* 0x464 p148, 2 lines */ +#define VE_RST_VALID 0x00000003ul /* 0x468 p148, 2 lines */ +#define G2D_RST_VALID 0x00000007ul /* 0x46c p148, 3 lines */ +#define VI_RST_VALID 0x00000007ul /* 0x470 p149, 3 lines */ +#define DVP_RST_VALID 0x00000001ul /* 0x474 p149, 1 line */ +#define ISP0_RST_VALID 0x00000001ul /* 0x478 p149, 1 line */ +#define ISP1_RST_VALID 0x00000001ul /* 0x47c p149, 1 line */ +#define SHUTTER_RST_VALID 0x0000003ful /* 0x480 p149, 6 lines */ +#define VOPHY_RST_VALID 0x0000003bul /* 0x484 p149, 5 lines */ +#define VOI2S_RST_VALID 0x00000003ul /* 0x488 p149, 2 lines */ +#define VO_RST_VALID 0x0000000ful /* 0x48c p150, 4 lines */ +#define BOOTSPI_RST_VALID 0x00000003ul /* 0x490 p150, 2 lines */ +#define I2C1_RST_VALID 0x00000001ul /* 0x494 p150, 1 line */ +#define I2C0_RST_VALID 0x00000001ul /* 0x498 p150, 1 line */ +#define FPRT_RST_VALID 0x00000001ul /* 0x4a0 p150, 1 line */ +#define HBLOCK_RST_VALID 0x00000001ul /* 0x4a4 p150, 1 line */ +#define SECSR_RST_VALID 0x00000001ul /* 0x4a8 p150, 1 line */ +#define OTP_RST_VALID 0x00000001ul /* 0x4ac p150, 1 line */ +#define PKA_RST_VALID 0x00000001ul /* 0x4b0 p151, 1 line */ +#define SPACC_RST_VALID 0x00000001ul /* 0x4b4 p151, 1 line */ +#define TRNG_RST_VALID 0x00000001ul /* 0x4b8 p151, 1 line */ +#define TIMER0_RST_VALID 0x000001fful /* 0x4c0 p151, 9 lines */ +#define TIMER1_RST_VALID 0x000001fful /* 0x4c4 p151, 9 lines */ +#define TIMER2_RST_VALID 0x000001fful /* 0x4c8 p151, 9 lines */ +#define TIMER3_RST_VALID 0x000001fful /* 0x4cc p151, 9 lines */ +#define RTC_RST_VALID 0x00000001ul /* 0x4d0 p151, 1 line */ +#define MNOC_RST_VALID 0x0000007ful /* 0x4d4 p151, 7 lines */ +#define RNOC_RST_VALID 0x0000003ful /* 0x4d8 p152, 6 lines */ +#define CNOC_RST_VALID 0x0000fffful /* 0x4dc p152, 16 lines */ +#define LNOC_RST_VALID 0x0000000ful /* 0x4e0 p153, 4 lines */ +#define PIPE_RST_VALID 0x01fffffful /* 0x4e4 p153, 25 lines */ +#define TBU_RST_VALID 0x0000000ful /* 0x4e8 p155, 4 lines */ +#define STATUS_RST_VALID 0x00000001ul /* 0x4ec p155, 1 line */ +#define TEST_RST_VALID 0x00000003ul /* 0x4f0 p155, 2 lines */ + +#endif /* __ARCH_RISCV_SRC_EIC7700X_HARDWARE_EIC7700X_RESET_H */ From 32f4bfa5b8dd1f8e8b49787464ed2b645184df82 Mon Sep 17 00:00:00 2001 From: Justin Hammond Date: Sun, 16 Aug 2026 02:23:39 +0800 Subject: [PATCH 2/4] boards/risc-v/eic7700x: Report the reset lines at startup. A peripheral held in reset reads like one that is absent, and the boot loader does not leave the same lines released on every board or every boot. One line at startup says how much is held: reset: 324 lines, 117 held Beside the clock tree's line and for the same reason: the summary is worth seeing on every boot, and the detail belongs in /proc where it can be read when it is wanted. The driver's error output is enabled, matching the clock driver. Info level is not, since nothing at that level prints on a healthy boot. Assisted-by: Claude:claude-opus-5 Signed-off-by: Justin Hammond --- .../eic7700x/common/src/eic7700x_boot.c | 20 +++++++++++++++++++ .../eic7700-evb/configs/nsh/defconfig | 2 ++ .../eic7700x/starpro64/configs/nsh/defconfig | 2 ++ 3 files changed, 24 insertions(+) diff --git a/boards/risc-v/eic7700x/common/src/eic7700x_boot.c b/boards/risc-v/eic7700x/common/src/eic7700x_boot.c index 3d86b3420ccf0..ac09f04ddb5b9 100644 --- a/boards/risc-v/eic7700x/common/src/eic7700x_boot.c +++ b/boards/risc-v/eic7700x/common/src/eic7700x_boot.c @@ -41,6 +41,7 @@ #ifdef CONFIG_EIC7700X_CPUCLK # include "eic7700x_cpuclk.h" #endif +#include "eic7700x_reset.h" #include "board_config.h" @@ -117,6 +118,24 @@ static void report_clocks(void) syslog(LOG_INFO, "clk: registered %u clocks, %u failed\n", nclk, nfail); } +/**************************************************************************** + * Name: report_resets + * + * Description: + * Report the reset lines the architecture registered before this board + * ran, and how many the boot loader left held. Its own function for the + * same reason as report_clocks(). + * + ****************************************************************************/ + +static void report_resets(void) +{ + unsigned int held; + unsigned int nline = eic7700x_reset_count(&held); + + syslog(LOG_INFO, "reset: %u lines, %u held\n", nline, held); +} + /**************************************************************************** * Name: board_late_initialize * @@ -156,6 +175,7 @@ void board_late_initialize(void) mount(NULL, "/proc", "procfs", 0, NULL); report_clocks(); + report_resets(); /* Devices whose presence or order is this board's business */ diff --git a/boards/risc-v/eic7700x/eic7700-evb/configs/nsh/defconfig b/boards/risc-v/eic7700x/eic7700-evb/configs/nsh/defconfig index ce4a8a086acc8..252bf2a674a37 100644 --- a/boards/risc-v/eic7700x/eic7700-evb/configs/nsh/defconfig +++ b/boards/risc-v/eic7700x/eic7700-evb/configs/nsh/defconfig @@ -63,6 +63,8 @@ CONFIG_DEBUG_FS_ERROR=y CONFIG_DEBUG_FULLOPT=y CONFIG_DEBUG_MM=y CONFIG_DEBUG_MM_ERROR=y +CONFIG_DEBUG_RESET=y +CONFIG_DEBUG_RESET_ERROR=y CONFIG_DEBUG_SCHED=y CONFIG_DEBUG_SYMBOLS=y CONFIG_DEFAULT_TASK_STACKSIZE=8192 diff --git a/boards/risc-v/eic7700x/starpro64/configs/nsh/defconfig b/boards/risc-v/eic7700x/starpro64/configs/nsh/defconfig index 88dbbc3a19552..72e92019e2e46 100644 --- a/boards/risc-v/eic7700x/starpro64/configs/nsh/defconfig +++ b/boards/risc-v/eic7700x/starpro64/configs/nsh/defconfig @@ -59,6 +59,8 @@ CONFIG_DEBUG_FS_ERROR=y CONFIG_DEBUG_FULLOPT=y CONFIG_DEBUG_MM=y CONFIG_DEBUG_MM_ERROR=y +CONFIG_DEBUG_RESET=y +CONFIG_DEBUG_RESET_ERROR=y CONFIG_DEBUG_SCHED=y CONFIG_DEBUG_SYMBOLS=y CONFIG_DEFAULT_TASK_STACKSIZE=8192 From 1bfdf6a099faa04eef8e1129508fd6331cd0d1ae Mon Sep 17 00:00:00 2001 From: Justin Hammond Date: Sun, 2 Aug 2026 16:11:01 +0800 Subject: [PATCH 3/4] arch/risc-v/eic7700x: Name the reset lines through procfs. Implements get_line, so /proc/reset names all 324 lines and gives the register and bit each lives in. The framework asks status() for the asserted state. The names do not survive compilation: they live in the enumeration, so without a table a listing gives only numbers, and working back from one to a peripheral means counting through the header. The table costs about 8 KiB and is built only when the procfs entry is. The ids are sparse, 324 lines across a space of 1952, so the table is sorted by id and searched rather than indexed, and an id naming no line returns -ENODEV. The framework skips those, which is what leaves the listing dense. Assisted-by: Claude:claude-opus-5 Signed-off-by: Justin Hammond --- arch/risc-v/src/eic7700x/eic7700x_reset.c | 430 ++++++++++++++++++ arch/risc-v/src/eic7700x/eic7700x_reset.h | 23 + arch/risc-v/src/eic7700x/eic7700x_reset_ops.c | 3 + 3 files changed, 456 insertions(+) diff --git a/arch/risc-v/src/eic7700x/eic7700x_reset.c b/arch/risc-v/src/eic7700x/eic7700x_reset.c index 479a3e261558b..fa75ba170f6a8 100644 --- a/arch/risc-v/src/eic7700x/eic7700x_reset.c +++ b/arch/risc-v/src/eic7700x/eic7700x_reset.c @@ -34,6 +34,10 @@ #include #include +#ifdef CONFIG_RESET_PROCFS +# include +# include +#endif #include "riscv_internal.h" #include "eic7700x_reset.h" @@ -95,6 +99,13 @@ static struct reset_controller_dev g_eic7700x_rcdev = { .name = EIC7700X_RESET_CONTROLLER, .ops = &g_eic7700x_reset_ops, +#ifdef CONFIG_RESET_PROCFS + /* The id space, not the line count: an id is a register index times + * thirty two plus a bit, and most of it names nothing. + */ + + .nlines = EIC7700X_RESET_ID(EIC7700X_RESET_NREGS, 0), +#endif }; /**************************************************************************** @@ -195,6 +206,425 @@ static_assert(EIC7700X_RESET_CTRL(EIC7700X_RESET_NREGS - 1) == * Private Functions ****************************************************************************/ +#ifdef CONFIG_RESET_PROCFS + +/* One reset line and the manual's name for it. Only built when the procfs + * entry is, since nothing else needs a line to have a name at run time: the + * enumeration carries the names everywhere else and does not survive + * compilation. + */ + +struct eic7700x_reset_name_s +{ + FAR const char *name; + uint16_t id; +}; + +#define RSTNAME(i, n) \ + { \ + .name = (n), .id = (i) \ + } + +static const struct eic7700x_reset_name_s g_eic7700x_reset_names[] = +{ + RSTNAME(EIC7700X_RESET_NOC_NSP, "noc_nsp"), + RSTNAME(EIC7700X_RESET_NOC_CFG, "noc_cfg"), + RSTNAME(EIC7700X_RESET_RNOC_NSP, "rnoc_nsp"), + RSTNAME(EIC7700X_RESET_SNOC_TCU_A, "snoc_tcu_a"), + RSTNAME(EIC7700X_RESET_SNOC_U84_A, "snoc_u84_a"), + RSTNAME(EIC7700X_RESET_SNOC_PCIET_XS, "snoc_pciet_xs"), + RSTNAME(EIC7700X_RESET_SNOC_PCIET_XM, "snoc_pciet_xm"), + RSTNAME(EIC7700X_RESET_SNOC_PCIET_P, "snoc_pciet_p"), + RSTNAME(EIC7700X_RESET_SNOC_NPU_A, "snoc_npu_a"), + RSTNAME(EIC7700X_RESET_SNOC_JTAG_P, "snoc_jtag_p"), + RSTNAME(EIC7700X_RESET_SNOC_DSPT_A, "snoc_dspt_a"), + RSTNAME(EIC7700X_RESET_SNOC_DDRC1_P2_A, "snoc_ddrc1_p2_a"), + RSTNAME(EIC7700X_RESET_SNOC_DDRC1_P1_A, "snoc_ddrc1_p1_a"), + RSTNAME(EIC7700X_RESET_SNOC_DDRC0_P2_A, "snoc_ddrc0_p2_a"), + RSTNAME(EIC7700X_RESET_SNOC_DDRC0_P1_A, "snoc_ddrc0_p1_a"), + RSTNAME(EIC7700X_RESET_SNOC_D2D_A, "snoc_d2d_a"), + RSTNAME(EIC7700X_RESET_SNOC_AON_A, "snoc_aon_a"), + RSTNAME(EIC7700X_RESET_GPU_AXI, "gpu_axi"), + RSTNAME(EIC7700X_RESET_GPU_CFG, "gpu_cfg"), + RSTNAME(EIC7700X_RESET_GPU_GRAY, "gpu_gray"), + RSTNAME(EIC7700X_RESET_GPU_JONES, "gpu_jones"), + RSTNAME(EIC7700X_RESET_GPU_SPU, "gpu_spu"), + RSTNAME(EIC7700X_RESET_DSP_AXI, "dsp_axi"), + RSTNAME(EIC7700X_RESET_DSP_CFG, "dsp_cfg"), + RSTNAME(EIC7700X_RESET_DSP_DIV4, "dsp_div4"), + RSTNAME(EIC7700X_RESET_DSP_DIV0, "dsp_div0"), + RSTNAME(EIC7700X_RESET_DSP_DIV1, "dsp_div1"), + RSTNAME(EIC7700X_RESET_DSP_DIV2, "dsp_div2"), + RSTNAME(EIC7700X_RESET_DSP_DIV3, "dsp_div3"), + RSTNAME(EIC7700X_RESET_D2D_AXI, "d2d_axi"), + RSTNAME(EIC7700X_RESET_D2D_CFG, "d2d_cfg"), + RSTNAME(EIC7700X_RESET_D2D_P, "d2d_p"), + RSTNAME(EIC7700X_RESET_D2D_RAW_PCS, "d2d_raw_pcs"), + RSTNAME(EIC7700X_RESET_D2D_RX, "d2d_rx"), + RSTNAME(EIC7700X_RESET_D2D_TX, "d2d_tx"), + RSTNAME(EIC7700X_RESET_D2D_CORE, "d2d_core"), + RSTNAME(EIC7700X_RESET_D2D_SUBSYS, "d2d_subsys"), + RSTNAME(EIC7700X_RESET_DDR1_P0_A, "ddr1_p0_a"), + RSTNAME(EIC7700X_RESET_DDR1_P1_A, "ddr1_p1_a"), + RSTNAME(EIC7700X_RESET_DDR1_P2_A, "ddr1_p2_a"), + RSTNAME(EIC7700X_RESET_DDR1_P3_A, "ddr1_p3_a"), + RSTNAME(EIC7700X_RESET_DDR1_P4_A, "ddr1_p4_a"), + RSTNAME(EIC7700X_RESET_DDR1_TRACE_A, "ddr1_trace_a"), + RSTNAME(EIC7700X_RESET_DDR1_PMP_SOFT, "ddr1_pmp_soft"), + RSTNAME(EIC7700X_RESET_DDR0_P0_A, "ddr0_p0_a"), + RSTNAME(EIC7700X_RESET_DDR0_P1_A, "ddr0_p1_a"), + RSTNAME(EIC7700X_RESET_DDR0_P2_A, "ddr0_p2_a"), + RSTNAME(EIC7700X_RESET_DDR0_P3_A, "ddr0_p3_a"), + RSTNAME(EIC7700X_RESET_DDR0_P4_A, "ddr0_p4_a"), + RSTNAME(EIC7700X_RESET_DDR_CFG, "ddr_cfg"), + RSTNAME(EIC7700X_RESET_DDR0_TRACE_A, "ddr0_trace_a"), + RSTNAME(EIC7700X_RESET_DDR_CORE, "ddr_core"), + RSTNAME(EIC7700X_RESET_DDR0_PMP_SOFT, "ddr0_pmp_soft"), + RSTNAME(EIC7700X_RESET_DDR_P, "ddr_p"), + RSTNAME(EIC7700X_RESET_TCU_AXI, "tcu_axi"), + RSTNAME(EIC7700X_RESET_TCU_CFG, "tcu_cfg"), + RSTNAME(EIC7700X_RESET_TCU_TBU0, "tcu_tbu0"), + RSTNAME(EIC7700X_RESET_TCU_TBU1, "tcu_tbu1"), + RSTNAME(EIC7700X_RESET_TCU_TBU2, "tcu_tbu2"), + RSTNAME(EIC7700X_RESET_TCU_TBU3, "tcu_tbu3"), + RSTNAME(EIC7700X_RESET_TCU_TBU4, "tcu_tbu4"), + RSTNAME(EIC7700X_RESET_TCU_TBU5, "tcu_tbu5"), + RSTNAME(EIC7700X_RESET_TCU_TBU6, "tcu_tbu6"), + RSTNAME(EIC7700X_RESET_TCU_TBU7, "tcu_tbu7"), + RSTNAME(EIC7700X_RESET_TCU_TBU8, "tcu_tbu8"), + RSTNAME(EIC7700X_RESET_TCU_TBU9, "tcu_tbu9"), + RSTNAME(EIC7700X_RESET_TCU_TBU10, "tcu_tbu10"), + RSTNAME(EIC7700X_RESET_TCU_TBU11, "tcu_tbu11"), + RSTNAME(EIC7700X_RESET_TCU_TBU12, "tcu_tbu12"), + RSTNAME(EIC7700X_RESET_TCU_TBU13, "tcu_tbu13"), + RSTNAME(EIC7700X_RESET_TCU_TBU14, "tcu_tbu14"), + RSTNAME(EIC7700X_RESET_TCU_TBU15, "tcu_tbu15"), + RSTNAME(EIC7700X_RESET_TCU_TBU16, "tcu_tbu16"), + RSTNAME(EIC7700X_RESET_NPU_AXI, "npu_axi"), + RSTNAME(EIC7700X_RESET_NPU_CFG, "npu_cfg"), + RSTNAME(EIC7700X_RESET_NPU_CORE, "npu_core"), + RSTNAME(EIC7700X_RESET_NPU_E31CORE, "npu_e31core"), + RSTNAME(EIC7700X_RESET_NPU_E31BUS, "npu_e31bus"), + RSTNAME(EIC7700X_RESET_NPU_E31DBG, "npu_e31dbg"), + RSTNAME(EIC7700X_RESET_NPU_LLC, "npu_llc"), + RSTNAME(EIC7700X_RESET_HSP_AXI, "hsp_axi"), + RSTNAME(EIC7700X_RESET_HSP_CFG, "hsp_cfg"), + RSTNAME(EIC7700X_RESET_HSP_POR, "hsp_por"), + RSTNAME(EIC7700X_RESET_MSHC0_PHY, "mshc0_phy"), + RSTNAME(EIC7700X_RESET_MSHC1_PHY, "mshc1_phy"), + RSTNAME(EIC7700X_RESET_MSHC2_PHY, "mshc2_phy"), + RSTNAME(EIC7700X_RESET_MSHC0_TXRX, "mshc0_txrx"), + RSTNAME(EIC7700X_RESET_MSHC1_TXRX, "mshc1_txrx"), + RSTNAME(EIC7700X_RESET_MSHC2_TXRX, "mshc2_txrx"), + RSTNAME(EIC7700X_RESET_SATA_ASIC0, "sata_asic0"), + RSTNAME(EIC7700X_RESET_SATA_OOB, "sata_oob"), + RSTNAME(EIC7700X_RESET_SATA_PMALIVE, "sata_pmalive"), + RSTNAME(EIC7700X_RESET_SATA_RBC, "sata_rbc"), + RSTNAME(EIC7700X_RESET_DMA0, "dma0"), + RSTNAME(EIC7700X_RESET_HSP_DMA0, "hsp_dma0"), + RSTNAME(EIC7700X_RESET_USB0_VAUX, "usb0_vaux"), + RSTNAME(EIC7700X_RESET_USB1_VAUX, "usb1_vaux"), + RSTNAME(EIC7700X_RESET_HSP_SD1_P, "hsp_sd1_p"), + RSTNAME(EIC7700X_RESET_HSP_SD0_P, "hsp_sd0_p"), + RSTNAME(EIC7700X_RESET_HSP_EMMC_P, "hsp_emmc_p"), + RSTNAME(EIC7700X_RESET_HSP_DMA_P, "hsp_dma_p"), + RSTNAME(EIC7700X_RESET_HSP_SD1_A, "hsp_sd1_a"), + RSTNAME(EIC7700X_RESET_HSP_SD0_A, "hsp_sd0_a"), + RSTNAME(EIC7700X_RESET_HSP_EMMC_A, "hsp_emmc_a"), + RSTNAME(EIC7700X_RESET_HSP_DMA_A, "hsp_dma_a"), + RSTNAME(EIC7700X_RESET_HSP_ETH1_A, "hsp_eth1_a"), + RSTNAME(EIC7700X_RESET_HSP_ETH0_A, "hsp_eth0_a"), + RSTNAME(EIC7700X_RESET_HSP_SATA_A, "hsp_sata_a"), + RSTNAME(EIC7700X_RESET_PCIE_CFG, "pcie_cfg"), + RSTNAME(EIC7700X_RESET_PCIE_POWERUP, "pcie_powerup"), + RSTNAME(EIC7700X_RESET_PCIE_PERST, "pcie_perst"), + RSTNAME(EIC7700X_RESET_I2C0, "i2c0"), + RSTNAME(EIC7700X_RESET_I2C1, "i2c1"), + RSTNAME(EIC7700X_RESET_I2C2, "i2c2"), + RSTNAME(EIC7700X_RESET_I2C3, "i2c3"), + RSTNAME(EIC7700X_RESET_I2C4, "i2c4"), + RSTNAME(EIC7700X_RESET_I2C5, "i2c5"), + RSTNAME(EIC7700X_RESET_I2C6, "i2c6"), + RSTNAME(EIC7700X_RESET_I2C7, "i2c7"), + RSTNAME(EIC7700X_RESET_I2C8, "i2c8"), + RSTNAME(EIC7700X_RESET_I2C9, "i2c9"), + RSTNAME(EIC7700X_RESET_FAN, "fan"), + RSTNAME(EIC7700X_RESET_PVT_LSP, "pvt_lsp"), + RSTNAME(EIC7700X_RESET_PVT_DDR, "pvt_ddr"), + RSTNAME(EIC7700X_RESET_MBOX0, "mbox0"), + RSTNAME(EIC7700X_RESET_MBOX1, "mbox1"), + RSTNAME(EIC7700X_RESET_MBOX2, "mbox2"), + RSTNAME(EIC7700X_RESET_MBOX3, "mbox3"), + RSTNAME(EIC7700X_RESET_MBOX4, "mbox4"), + RSTNAME(EIC7700X_RESET_MBOX5, "mbox5"), + RSTNAME(EIC7700X_RESET_MBOX6, "mbox6"), + RSTNAME(EIC7700X_RESET_MBOX7, "mbox7"), + RSTNAME(EIC7700X_RESET_MBOX8, "mbox8"), + RSTNAME(EIC7700X_RESET_MBOX9, "mbox9"), + RSTNAME(EIC7700X_RESET_MBOX10, "mbox10"), + RSTNAME(EIC7700X_RESET_MBOX11, "mbox11"), + RSTNAME(EIC7700X_RESET_MBOX12, "mbox12"), + RSTNAME(EIC7700X_RESET_MBOX13, "mbox13"), + RSTNAME(EIC7700X_RESET_MBOX14, "mbox14"), + RSTNAME(EIC7700X_RESET_MBOX15, "mbox15"), + RSTNAME(EIC7700X_RESET_UART0, "uart0"), + RSTNAME(EIC7700X_RESET_UART1, "uart1"), + RSTNAME(EIC7700X_RESET_UART2, "uart2"), + RSTNAME(EIC7700X_RESET_UART3, "uart3"), + RSTNAME(EIC7700X_RESET_UART4, "uart4"), + RSTNAME(EIC7700X_RESET_GPIO0, "gpio0"), + RSTNAME(EIC7700X_RESET_GPIO1, "gpio1"), + RSTNAME(EIC7700X_RESET_LSP_TIMER, "lsp_timer"), + RSTNAME(EIC7700X_RESET_SSI0, "ssi0"), + RSTNAME(EIC7700X_RESET_SSI1, "ssi1"), + RSTNAME(EIC7700X_RESET_WDT0, "wdt0"), + RSTNAME(EIC7700X_RESET_WDT1, "wdt1"), + RSTNAME(EIC7700X_RESET_WDT2, "wdt2"), + RSTNAME(EIC7700X_RESET_WDT3, "wdt3"), + RSTNAME(EIC7700X_RESET_LSP_CFG, "lsp_cfg"), + RSTNAME(EIC7700X_RESET_U84_CORE0, "u84_core0"), + RSTNAME(EIC7700X_RESET_U84_CORE1, "u84_core1"), + RSTNAME(EIC7700X_RESET_U84_CORE2, "u84_core2"), + RSTNAME(EIC7700X_RESET_U84_CORE3, "u84_core3"), + RSTNAME(EIC7700X_RESET_U84_BUS, "u84_bus"), + RSTNAME(EIC7700X_RESET_U84_DBG, "u84_dbg"), + RSTNAME(EIC7700X_RESET_U84_TRACECOM, "u84_tracecom"), + RSTNAME(EIC7700X_RESET_U84_TRACE0, "u84_trace0"), + RSTNAME(EIC7700X_RESET_U84_TRACE1, "u84_trace1"), + RSTNAME(EIC7700X_RESET_U84_TRACE2, "u84_trace2"), + RSTNAME(EIC7700X_RESET_U84_TRACE3, "u84_trace3"), + RSTNAME(EIC7700X_RESET_SCPU_CORE, "scpu_core"), + RSTNAME(EIC7700X_RESET_SCPU_BUS, "scpu_bus"), + RSTNAME(EIC7700X_RESET_SCPU_DBG, "scpu_dbg"), + RSTNAME(EIC7700X_RESET_LPCPU_CORE, "lpcpu_core"), + RSTNAME(EIC7700X_RESET_LPCPU_BUS, "lpcpu_bus"), + RSTNAME(EIC7700X_RESET_LPCPU_DBG, "lpcpu_dbg"), + RSTNAME(EIC7700X_RESET_VC_CFG, "vc_cfg"), + RSTNAME(EIC7700X_RESET_VC_AXI, "vc_axi"), + RSTNAME(EIC7700X_RESET_VC_MONCFG, "vc_moncfg"), + RSTNAME(EIC7700X_RESET_JD_CFG, "jd_cfg"), + RSTNAME(EIC7700X_RESET_JD_AXI, "jd_axi"), + RSTNAME(EIC7700X_RESET_JE_CFG, "je_cfg"), + RSTNAME(EIC7700X_RESET_JE_AXI, "je_axi"), + RSTNAME(EIC7700X_RESET_VD_CFG, "vd_cfg"), + RSTNAME(EIC7700X_RESET_VD_AXI, "vd_axi"), + RSTNAME(EIC7700X_RESET_VE_CFG, "ve_cfg"), + RSTNAME(EIC7700X_RESET_VE_AXI, "ve_axi"), + RSTNAME(EIC7700X_RESET_G2D_CORE, "g2d_core"), + RSTNAME(EIC7700X_RESET_G2D_CFG, "g2d_cfg"), + RSTNAME(EIC7700X_RESET_G2D_AXI, "g2d_axi"), + RSTNAME(EIC7700X_RESET_VI_AXI, "vi_axi"), + RSTNAME(EIC7700X_RESET_VI_CFG, "vi_cfg"), + RSTNAME(EIC7700X_RESET_VI_DWE, "vi_dwe"), + RSTNAME(EIC7700X_RESET_VI_DVP, "vi_dvp"), + RSTNAME(EIC7700X_RESET_VI_ISP0, "vi_isp0"), + RSTNAME(EIC7700X_RESET_VI_ISP1, "vi_isp1"), + RSTNAME(EIC7700X_RESET_VI_SHUTTER0, "vi_shutter0"), + RSTNAME(EIC7700X_RESET_VI_SHUTTER1, "vi_shutter1"), + RSTNAME(EIC7700X_RESET_VI_SHUTTER2, "vi_shutter2"), + RSTNAME(EIC7700X_RESET_VI_SHUTTER3, "vi_shutter3"), + RSTNAME(EIC7700X_RESET_VI_SHUTTER4, "vi_shutter4"), + RSTNAME(EIC7700X_RESET_VI_SHUTTER5, "vi_shutter5"), + RSTNAME(EIC7700X_RESET_VO_MIPI_P, "vo_mipi_p"), + RSTNAME(EIC7700X_RESET_VO_P, "vo_p"), + RSTNAME(EIC7700X_RESET_VO_HDMI_P, "vo_hdmi_p"), + RSTNAME(EIC7700X_RESET_HDMI_PHYCTRL, "hdmi_phyctrl"), + RSTNAME(EIC7700X_RESET_VO_HDMI, "vo_hdmi"), + RSTNAME(EIC7700X_RESET_VO_I2S, "vo_i2s"), + RSTNAME(EIC7700X_RESET_VO_I2S_P, "vo_i2s_p"), + RSTNAME(EIC7700X_RESET_VO_AXI, "vo_axi"), + RSTNAME(EIC7700X_RESET_VO_CFG, "vo_cfg"), + RSTNAME(EIC7700X_RESET_VO_DC, "vo_dc"), + RSTNAME(EIC7700X_RESET_VO_DC_P, "vo_dc_p"), + RSTNAME(EIC7700X_RESET_BOOTSPI_H, "bootspi_h"), + RSTNAME(EIC7700X_RESET_BOOTSPI, "bootspi"), + RSTNAME(EIC7700X_RESET_I2C1_P, "i2c1_p"), + RSTNAME(EIC7700X_RESET_I2C0_P, "i2c0_p"), + RSTNAME(EIC7700X_RESET_DMA1_A, "dma1_a"), + RSTNAME(EIC7700X_RESET_DMA1_H, "dma1_h"), + RSTNAME(EIC7700X_RESET_FPRT_H, "fprt_h"), + RSTNAME(EIC7700X_RESET_HBLOCK_H, "hblock_h"), + RSTNAME(EIC7700X_RESET_SECSR_H, "secsr_h"), + RSTNAME(EIC7700X_RESET_OTP_P, "otp_p"), + RSTNAME(EIC7700X_RESET_PKA_H, "pka_h"), + RSTNAME(EIC7700X_RESET_SPACC, "spacc"), + RSTNAME(EIC7700X_RESET_TRNG_H, "trng_h"), + RSTNAME(EIC7700X_RESET_TIMER0_CNT0, "timer0_cnt0"), + RSTNAME(EIC7700X_RESET_TIMER0_CNT1, "timer0_cnt1"), + RSTNAME(EIC7700X_RESET_TIMER0_CNT2, "timer0_cnt2"), + RSTNAME(EIC7700X_RESET_TIMER0_CNT3, "timer0_cnt3"), + RSTNAME(EIC7700X_RESET_TIMER0_CNT4, "timer0_cnt4"), + RSTNAME(EIC7700X_RESET_TIMER0_CNT5, "timer0_cnt5"), + RSTNAME(EIC7700X_RESET_TIMER0_CNT6, "timer0_cnt6"), + RSTNAME(EIC7700X_RESET_TIMER0_CNT7, "timer0_cnt7"), + RSTNAME(EIC7700X_RESET_TIMER0_P, "timer0_p"), + RSTNAME(EIC7700X_RESET_TIMER1_CNT0, "timer1_cnt0"), + RSTNAME(EIC7700X_RESET_TIMER1_CNT1, "timer1_cnt1"), + RSTNAME(EIC7700X_RESET_TIMER1_CNT2, "timer1_cnt2"), + RSTNAME(EIC7700X_RESET_TIMER1_CNT3, "timer1_cnt3"), + RSTNAME(EIC7700X_RESET_TIMER1_CNT4, "timer1_cnt4"), + RSTNAME(EIC7700X_RESET_TIMER1_CNT5, "timer1_cnt5"), + RSTNAME(EIC7700X_RESET_TIMER1_CNT6, "timer1_cnt6"), + RSTNAME(EIC7700X_RESET_TIMER1_CNT7, "timer1_cnt7"), + RSTNAME(EIC7700X_RESET_TIMER1_P, "timer1_p"), + RSTNAME(EIC7700X_RESET_TIMER2_CNT0, "timer2_cnt0"), + RSTNAME(EIC7700X_RESET_TIMER2_CNT1, "timer2_cnt1"), + RSTNAME(EIC7700X_RESET_TIMER2_CNT2, "timer2_cnt2"), + RSTNAME(EIC7700X_RESET_TIMER2_CNT3, "timer2_cnt3"), + RSTNAME(EIC7700X_RESET_TIMER2_CNT4, "timer2_cnt4"), + RSTNAME(EIC7700X_RESET_TIMER2_CNT5, "timer2_cnt5"), + RSTNAME(EIC7700X_RESET_TIMER2_CNT6, "timer2_cnt6"), + RSTNAME(EIC7700X_RESET_TIMER2_CNT7, "timer2_cnt7"), + RSTNAME(EIC7700X_RESET_TIMER2_P, "timer2_p"), + RSTNAME(EIC7700X_RESET_TIMER3_CNT0, "timer3_cnt0"), + RSTNAME(EIC7700X_RESET_TIMER3_CNT1, "timer3_cnt1"), + RSTNAME(EIC7700X_RESET_TIMER3_CNT2, "timer3_cnt2"), + RSTNAME(EIC7700X_RESET_TIMER3_CNT3, "timer3_cnt3"), + RSTNAME(EIC7700X_RESET_TIMER3_CNT4, "timer3_cnt4"), + RSTNAME(EIC7700X_RESET_TIMER3_CNT5, "timer3_cnt5"), + RSTNAME(EIC7700X_RESET_TIMER3_CNT6, "timer3_cnt6"), + RSTNAME(EIC7700X_RESET_TIMER3_CNT7, "timer3_cnt7"), + RSTNAME(EIC7700X_RESET_TIMER3_P, "timer3_p"), + RSTNAME(EIC7700X_RESET_RTC, "rtc"), + RSTNAME(EIC7700X_RESET_MNOC_SNOC_NSP, "mnoc_snoc_nsp"), + RSTNAME(EIC7700X_RESET_MNOC_VC_A, "mnoc_vc_a"), + RSTNAME(EIC7700X_RESET_MNOC_CFG, "mnoc_cfg"), + RSTNAME(EIC7700X_RESET_MNOC_HSP_A, "mnoc_hsp_a"), + RSTNAME(EIC7700X_RESET_MNOC_GPU_A, "mnoc_gpu_a"), + RSTNAME(EIC7700X_RESET_MNOC_DDRC1_P3_A, "mnoc_ddrc1_p3_a"), + RSTNAME(EIC7700X_RESET_MNOC_DDRC0_P3_A, "mnoc_ddrc0_p3_a"), + RSTNAME(EIC7700X_RESET_RNOC_VO_A, "rnoc_vo_a"), + RSTNAME(EIC7700X_RESET_RNOC_VI_A, "rnoc_vi_a"), + RSTNAME(EIC7700X_RESET_RNOC_SNOC_NSP, "rnoc_snoc_nsp"), + RSTNAME(EIC7700X_RESET_RNOC_CFG, "rnoc_cfg"), + RSTNAME(EIC7700X_RESET_RNOC_DDRC1_P4_A, "rnoc_ddrc1_p4_a"), + RSTNAME(EIC7700X_RESET_RNOC_DDRC0_P4_A, "rnoc_ddrc0_p4_a"), + RSTNAME(EIC7700X_RESET_CNOC_VO_CFG, "cnoc_vo_cfg"), + RSTNAME(EIC7700X_RESET_CNOC_VI_CFG, "cnoc_vi_cfg"), + RSTNAME(EIC7700X_RESET_CNOC_VC_CFG, "cnoc_vc_cfg"), + RSTNAME(EIC7700X_RESET_CNOC_TCU_CFG, "cnoc_tcu_cfg"), + RSTNAME(EIC7700X_RESET_CNOC_PCIET_CFG, "cnoc_pciet_cfg"), + RSTNAME(EIC7700X_RESET_CNOC_NPU_CFG, "cnoc_npu_cfg"), + RSTNAME(EIC7700X_RESET_CNOC_LSP_CFG, "cnoc_lsp_cfg"), + RSTNAME(EIC7700X_RESET_CNOC_HSP_CFG, "cnoc_hsp_cfg"), + RSTNAME(EIC7700X_RESET_CNOC_GPU_CFG, "cnoc_gpu_cfg"), + RSTNAME(EIC7700X_RESET_CNOC_DSPT_CFG, "cnoc_dspt_cfg"), + RSTNAME(EIC7700X_RESET_CNOC_DDRT1_CFG, "cnoc_ddrt1_cfg"), + RSTNAME(EIC7700X_RESET_CNOC_DDRT0_CFG, "cnoc_ddrt0_cfg"), + RSTNAME(EIC7700X_RESET_CNOC_D2D_CFG, "cnoc_d2d_cfg"), + RSTNAME(EIC7700X_RESET_CNOC_CFG, "cnoc_cfg"), + RSTNAME(EIC7700X_RESET_CNOC_CLMM_CFG, "cnoc_clmm_cfg"), + RSTNAME(EIC7700X_RESET_CNOC_AON_CFG, "cnoc_aon_cfg"), + RSTNAME(EIC7700X_RESET_LNOC_CFG, "lnoc_cfg"), + RSTNAME(EIC7700X_RESET_LNOC_NPU_LLC_A, "lnoc_npu_llc_a"), + RSTNAME(EIC7700X_RESET_LNOC_DDRC1_P0_A, "lnoc_ddrc1_p0_a"), + RSTNAME(EIC7700X_RESET_LNOC_DDRC0_P0_A, "lnoc_ddrc0_p0_a"), + RSTNAME(EIC7700X_RESET_PIPE_TBU2SNOC, "pipe_tbu2snoc"), + RSTNAME(EIC7700X_RESET_PIPE_TBU2MNOC, "pipe_tbu2mnoc"), + RSTNAME(EIC7700X_RESET_PIPE_SNOC2PCIE, "pipe_snoc2pcie"), + RSTNAME(EIC7700X_RESET_PIPE_SNOC2MNOC, "pipe_snoc2mnoc"), + RSTNAME(EIC7700X_RESET_PIPE_SNOC2DDR1P1, "pipe_snoc2ddr1p1"), + RSTNAME(EIC7700X_RESET_PIPE_SNOC2DDR0P1, "pipe_snoc2ddr0p1"), + RSTNAME(EIC7700X_RESET_PIPE_SNOC2DDR1P2, "pipe_snoc2ddr1p2"), + RSTNAME(EIC7700X_RESET_PIPE_SNOC2DDR0P2, "pipe_snoc2ddr0p2"), + RSTNAME(EIC7700X_RESET_PIPE_SNOC2D2D, "pipe_snoc2d2d"), + RSTNAME(EIC7700X_RESET_PIPE_MCPU2SNOC, "pipe_mcpu2snoc"), + RSTNAME(EIC7700X_RESET_PIPE_MCPU2SNOCSP, "pipe_mcpu2snocsp"), + RSTNAME(EIC7700X_RESET_PIPE_MNOC2SNOC, "pipe_mnoc2snoc"), + RSTNAME(EIC7700X_RESET_PIPE_LNOC2DDR1, "pipe_lnoc2ddr1"), + RSTNAME(EIC7700X_RESET_PIPE_LNOC2DDR0, "pipe_lnoc2ddr0"), + RSTNAME(EIC7700X_RESET_PIPE_RNOC2DDR1, "pipe_rnoc2ddr1"), + RSTNAME(EIC7700X_RESET_PIPE_RNOC2DDR0, "pipe_rnoc2ddr0"), + RSTNAME(EIC7700X_RESET_PIPE_MNOC2DDR0, "pipe_mnoc2ddr0"), + RSTNAME(EIC7700X_RESET_PIPE_SNOC2DSP, "pipe_snoc2dsp"), + RSTNAME(EIC7700X_RESET_PIPE_DSP2SNOC, "pipe_dsp2snoc"), + RSTNAME(EIC7700X_RESET_PIPE_DSP2TCU, "pipe_dsp2tcu"), + RSTNAME(EIC7700X_RESET_PIPE_PCIE2TCU, "pipe_pcie2tcu"), + RSTNAME(EIC7700X_RESET_PIPE_VI2RNOC, "pipe_vi2rnoc"), + RSTNAME(EIC7700X_RESET_PIPE_VO2RNOC, "pipe_vo2rnoc"), + RSTNAME(EIC7700X_RESET_PIPE_GPU2MNOC, "pipe_gpu2mnoc"), + RSTNAME(EIC7700X_RESET_PIPE_VC2MNOC, "pipe_vc2mnoc"), + RSTNAME(EIC7700X_RESET_TBU_AON_A, "tbu_aon_a"), + RSTNAME(EIC7700X_RESET_TBU_PCIET_TBU3, "tbu_pciet_tbu3"), + RSTNAME(EIC7700X_RESET_TBU_HSP_A, "tbu_hsp_a"), + RSTNAME(EIC7700X_RESET_TBU_VI_AXI, "tbu_vi_axi"), + RSTNAME(EIC7700X_RESET_EXT_D2D_STATUS, "ext_d2d_status"), + RSTNAME(EIC7700X_RESET_TESTMUX, "testmux"), + RSTNAME(EIC7700X_RESET_SPI_SLV, "spi_slv"), +}; + +static_assert(nitems(g_eic7700x_reset_names) == 324, + "reset name table does not cover every line"); + +/* eic7700x_reset_getline() binary searches this table, so it has to be in + * id order. Checking every pair at compile time is not expressible here; + * the ends catch a table rebuilt in the wrong order. + */ + +static_assert(EIC7700X_RESET_NOC_NSP < EIC7700X_RESET_SPI_SLV, + "reset name table must be sorted by id"); + +/**************************************************************************** + * Name: eic7700x_reset_getline + * + * Description: + * Describe one reset line for /proc/reset: its name, and the register + * and bit it lives in. The state is not reported here; the framework + * asks status() for it. + * + * The ids are a register index times thirty two plus a bit, so most of + * the space names nothing. The table is sorted by id, which makes the + * lookup a binary search and reports a gap as -ENODEV. + * + * Reads only. + * + * Input Parameters: + * rcdev - The reset controller + * id - The reset line id + * info - Receives the name, and the register and bit as extra text + * + * Returned Value: + * OK, or -ENODEV if the id names no line. + * + ****************************************************************************/ + +int eic7700x_reset_getline(FAR struct reset_controller_dev *rcdev, + unsigned int id, + FAR struct reset_lineinfo_s *info) +{ + unsigned int low = 0; + unsigned int high = nitems(g_eic7700x_reset_names); + + while (low < high) + { + unsigned int mid = low + (high - low) / 2; + unsigned int found = g_eic7700x_reset_names[mid].id; + + if (found == id) + { + strlcpy(info->name, g_eic7700x_reset_names[mid].name, + sizeof(info->name)); + snprintf(info->extra, sizeof(info->extra), "reg:0x%03x bit:%u", + (unsigned int)(0x400 + EIC7700X_RESET_REGOF(id) * 4), + EIC7700X_RESET_BITOF(id)); + return OK; + } + + if (found < id) + { + low = mid + 1; + } + else + { + high = mid; + } + } + + return -ENODEV; +} + +#endif /* CONFIG_RESET_PROCFS */ + /**************************************************************************** * Public Functions ****************************************************************************/ diff --git a/arch/risc-v/src/eic7700x/eic7700x_reset.h b/arch/risc-v/src/eic7700x/eic7700x_reset.h index 68c6cc5091a01..63b2af12ecaae 100644 --- a/arch/risc-v/src/eic7700x/eic7700x_reset.h +++ b/arch/risc-v/src/eic7700x/eic7700x_reset.h @@ -110,6 +110,29 @@ int eic7700x_reset_initialize(void); unsigned int eic7700x_reset_count(FAR unsigned int *held); +#ifdef CONFIG_RESET_PROCFS +/**************************************************************************** + * Name: eic7700x_reset_getline + * + * Description: + * Describe one reset line for /proc/reset. Lives beside the name table + * rather than beside the operations, since that is what it reads. + * + * Input Parameters: + * rcdev - The reset controller + * id - The reset line id + * info - Receives the name, and the register and bit as extra text + * + * Returned Value: + * OK, or -ENODEV if the id names no line. + * + ****************************************************************************/ + +int eic7700x_reset_getline(FAR struct reset_controller_dev *rcdev, + unsigned int id, + FAR struct reset_lineinfo_s *info); +#endif + #undef EXTERN #ifdef __cplusplus } diff --git a/arch/risc-v/src/eic7700x/eic7700x_reset_ops.c b/arch/risc-v/src/eic7700x/eic7700x_reset_ops.c index 062a3ea0af2e1..6d026f5751277 100644 --- a/arch/risc-v/src/eic7700x/eic7700x_reset_ops.c +++ b/arch/risc-v/src/eic7700x/eic7700x_reset_ops.c @@ -287,4 +287,7 @@ const struct reset_control_ops g_eic7700x_reset_ops = .assert = eic7700x_reset_assert, .deassert = eic7700x_reset_deassert, .status = eic7700x_reset_status, +#ifdef CONFIG_RESET_PROCFS + .get_line = eic7700x_reset_getline, +#endif }; From 571167ef0fff7a398d32784720746cc7f458e372 Mon Sep 17 00:00:00 2001 From: Justin Hammond Date: Sun, 2 Aug 2026 16:11:02 +0800 Subject: [PATCH 4/4] boards/risc-v/eic7700x: Enable the reset procfs entry. Makes /proc/reset available, so which peripherals are held can be read while the board is running rather than only for the eight lines the startup report names. RESET_PROCFS depends on FS_PROCFS_REGISTER, which neither board set. Without it the symbol is dropped when the configuration is regenerated and the entry never appears, which is silent: the defconfig still reads as though the feature were on. Assisted-by: Claude:claude-opus-5 Signed-off-by: Justin Hammond --- arch/risc-v/src/eic7700x/Kconfig | 1 + boards/risc-v/eic7700x/eic7700-evb/configs/nsh/defconfig | 2 ++ boards/risc-v/eic7700x/starpro64/configs/nsh/defconfig | 2 ++ 3 files changed, 5 insertions(+) diff --git a/arch/risc-v/src/eic7700x/Kconfig b/arch/risc-v/src/eic7700x/Kconfig index c015c8bc5a789..d7941c76e2cf5 100644 --- a/arch/risc-v/src/eic7700x/Kconfig +++ b/arch/risc-v/src/eic7700x/Kconfig @@ -48,6 +48,7 @@ config EIC7700X_CPU_FREQ_MHZ so in the log. endif + config EIC7700X_RESET bool "CRG reset provider" default y diff --git a/boards/risc-v/eic7700x/eic7700-evb/configs/nsh/defconfig b/boards/risc-v/eic7700x/eic7700-evb/configs/nsh/defconfig index 252bf2a674a37..5055e1808ea5f 100644 --- a/boards/risc-v/eic7700x/eic7700-evb/configs/nsh/defconfig +++ b/boards/risc-v/eic7700x/eic7700-evb/configs/nsh/defconfig @@ -73,6 +73,7 @@ CONFIG_ELF=y CONFIG_ELF_STACKSIZE=2048 CONFIG_EXAMPLES_HELLO=m CONFIG_FS_PROCFS=y +CONFIG_FS_PROCFS_REGISTER=y CONFIG_FS_ROMFS=y CONFIG_IDLETHREAD_STACKSIZE=3072 CONFIG_INIT_FILEPATH="/system/bin/init" @@ -99,6 +100,7 @@ CONFIG_RAM_SIZE=1006632960 CONFIG_RAM_START=0x80200000 CONFIG_RAW_BINARY=y CONFIG_READLINE_CMD_HISTORY=y +CONFIG_RESET_PROCFS=y CONFIG_RISCV_STRING_FUNCTION=y CONFIG_RR_INTERVAL=200 CONFIG_SCHED_BACKTRACE=y diff --git a/boards/risc-v/eic7700x/starpro64/configs/nsh/defconfig b/boards/risc-v/eic7700x/starpro64/configs/nsh/defconfig index 72e92019e2e46..db0fceabd781b 100644 --- a/boards/risc-v/eic7700x/starpro64/configs/nsh/defconfig +++ b/boards/risc-v/eic7700x/starpro64/configs/nsh/defconfig @@ -69,6 +69,7 @@ CONFIG_ELF=y CONFIG_ELF_STACKSIZE=2048 CONFIG_EXAMPLES_HELLO=m CONFIG_FS_PROCFS=y +CONFIG_FS_PROCFS_REGISTER=y CONFIG_FS_ROMFS=y CONFIG_IDLETHREAD_STACKSIZE=3072 CONFIG_INIT_FILEPATH="/system/bin/init" @@ -95,6 +96,7 @@ CONFIG_RAM_SIZE=1006632960 CONFIG_RAM_START=0x80200000 CONFIG_RAW_BINARY=y CONFIG_READLINE_CMD_HISTORY=y +CONFIG_RESET_PROCFS=y CONFIG_RISCV_STRING_FUNCTION=y CONFIG_RR_INTERVAL=200 CONFIG_SCHED_BACKTRACE=y