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..d7941c76e2cf5 100644 --- a/arch/risc-v/src/eic7700x/Kconfig +++ b/arch/risc-v/src/eic7700x/Kconfig @@ -47,4 +47,18 @@ 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..fa75ba170f6a8 --- /dev/null +++ b/arch/risc-v/src/eic7700x/eic7700x_reset.c @@ -0,0 +1,712 @@ +/**************************************************************************** + * 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 +#ifdef CONFIG_RESET_PROCFS +# include +# include +#endif + +#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, +#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 +}; + +/**************************************************************************** + * 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 + ****************************************************************************/ + +#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 + ****************************************************************************/ + +/**************************************************************************** + * 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..63b2af12ecaae --- /dev/null +++ b/arch/risc-v/src/eic7700x/eic7700x_reset.h @@ -0,0 +1,141 @@ +/**************************************************************************** + * 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); + +#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 +} +#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..6d026f5751277 --- /dev/null +++ b/arch/risc-v/src/eic7700x/eic7700x_reset_ops.c @@ -0,0 +1,293 @@ +/**************************************************************************** + * 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, +#ifdef CONFIG_RESET_PROCFS + .get_line = eic7700x_reset_getline, +#endif +}; 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 */ 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..5055e1808ea5f 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 @@ -71,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" @@ -97,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 88dbbc3a19552..db0fceabd781b 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 @@ -67,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" @@ -93,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