diff --git a/arch/arm/dts/sc57x.dtsi b/arch/arm/dts/sc57x.dtsi index e4cc612959fc..0c2ab77fb8aa 100644 --- a/arch/arm/dts/sc57x.dtsi +++ b/arch/arm/dts/sc57x.dtsi @@ -14,6 +14,15 @@ }; soc { + rcu: rcu@3108C000 { + compatible = "adi,reset-controller"; + reg = <0x3108C000 0x1000>; + adi,sharc-min = <1>; + adi,sharc-max = <2>; + adi,enable-reboot; + status = "okay"; + }; + mmc: mmc0@31010000 { compatible = "snps,dw-mshc"; reg = <0x31010000 0x400>; diff --git a/arch/arm/dts/sc58x.dtsi b/arch/arm/dts/sc58x.dtsi index 7b07589de47f..0ebf3b2b9c9e 100644 --- a/arch/arm/dts/sc58x.dtsi +++ b/arch/arm/dts/sc58x.dtsi @@ -16,13 +16,13 @@ }; soc { - rcu: rcu@0x3108B000 { + rcu: rcu@3108B000 { compatible = "adi,reset-controller"; reg = <0x3108B000 0x1000>; adi,sharc-min = <1>; adi,sharc-max = <2>; adi,enable-reboot; - status = "disabled"; + status = "okay"; }; mmc: mmc0@31010000 { diff --git a/arch/arm/dts/sc598-som.dtsi b/arch/arm/dts/sc598-som.dtsi index ac1f24c86c39..d58ba9e582e6 100644 --- a/arch/arm/dts/sc598-som.dtsi +++ b/arch/arm/dts/sc598-som.dtsi @@ -114,10 +114,6 @@ reg-names = "cgu0", "cgu1", "cdu", "pll3"; }; -&rcu { - status = "okay"; -}; - &uart0 { clocks = <&clk ADSP_SC598_CLK_CGU0_SCLK0>; }; diff --git a/arch/arm/dts/sc59x.dtsi b/arch/arm/dts/sc59x.dtsi index 64e5a1afc539..762ed8044ca4 100644 --- a/arch/arm/dts/sc59x.dtsi +++ b/arch/arm/dts/sc59x.dtsi @@ -10,12 +10,13 @@ }; soc { - rcu: rcu@0x3108C000 { + rcu: rcu@3108C000 { compatible = "adi,reset-controller"; reg = <0x3108C000 0x1000>; adi,sharc-min = <1>; adi,sharc-max = <2>; - status = "disabled"; + adi,enable-reboot; + status = "okay"; }; mdma: dma@0x310A7000 { diff --git a/arch/arm/mach-sc5xx/Makefile b/arch/arm/mach-sc5xx/Makefile index 4aaf94f6b9f5..00a1ec7457e3 100644 --- a/arch/arm/mach-sc5xx/Makefile +++ b/arch/arm/mach-sc5xx/Makefile @@ -17,4 +17,3 @@ obj-$(CONFIG_SC59X_64) += sc59x_64.o obj-$(CONFIG_SC59X_64) += sc59x_64-spl.o obj-$(CONFIG_XPL_BUILD) += spl.o -obj-$(CONFIG_SYSCON) += rcu.o diff --git a/arch/arm/mach-sc5xx/rcu.c b/arch/arm/mach-sc5xx/rcu.c deleted file mode 100644 index c9911be91d66..000000000000 --- a/arch/arm/mach-sc5xx/rcu.c +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * (C) Copyright 2024 - Analog Devices, Inc. - * - * Written by Timesys Corporation - * - */ - -#include -#include - -static const struct udevice_id adi_syscon_ids[] = { - { .compatible = "adi,reset-controller" }, - { } -}; - -U_BOOT_DRIVER(syscon_sc5xx_rcu) = { - .name = "sc5xx_rcu", - .id = UCLASS_SYSCON, - .of_match = adi_syscon_ids, -}; diff --git a/arch/arm/mach-sc5xx/soc.c b/arch/arm/mach-sc5xx/soc.c index 09978a5cf44d..412442443031 100644 --- a/arch/arm/mach-sc5xx/soc.c +++ b/arch/arm/mach-sc5xx/soc.c @@ -39,11 +39,13 @@ DECLARE_GLOBAL_DATA_PTR; +#if !CONFIG_IS_ENABLED(SYSRESET) void reset_cpu(void) { u32 val = readl(RCU0_CTL); writel(val | 1, RCU0_CTL); } +#endif void enable_caches(void) { diff --git a/configs/sc573-ezlite_defconfig b/configs/sc573-ezlite_defconfig index 802f0e524008..edfaecc8e61e 100644 --- a/configs/sc573-ezlite_defconfig +++ b/configs/sc573-ezlite_defconfig @@ -75,6 +75,8 @@ CONFIG_SPECIFY_CONSOLE_INDEX=y CONFIG_SPI=y CONFIG_DM_SPI=y CONFIG_ADI_SPI3=y +CONFIG_SYSRESET=y +CONFIG_SYSRESET_SC5XX=y CONFIG_SPL_TIMER=y CONFIG_USB=y CONFIG_USB_MUSB_HOST=y diff --git a/configs/sc584-ezkit_defconfig b/configs/sc584-ezkit_defconfig index 471f38fbb707..69ae8ccde092 100644 --- a/configs/sc584-ezkit_defconfig +++ b/configs/sc584-ezkit_defconfig @@ -78,6 +78,8 @@ CONFIG_SPECIFY_CONSOLE_INDEX=y CONFIG_SPI=y CONFIG_DM_SPI=y CONFIG_ADI_SPI3=y +CONFIG_SYSRESET=y +CONFIG_SYSRESET_SC5XX=y CONFIG_SPL_TIMER=y CONFIG_USB=y CONFIG_USB_MUSB_HOST=y diff --git a/configs/sc589-ezkit_defconfig b/configs/sc589-ezkit_defconfig index f5e3c7e28b32..8639bb03279d 100644 --- a/configs/sc589-ezkit_defconfig +++ b/configs/sc589-ezkit_defconfig @@ -84,6 +84,8 @@ CONFIG_SPECIFY_CONSOLE_INDEX=y CONFIG_SPI=y CONFIG_DM_SPI=y CONFIG_ADI_SPI3=y +CONFIG_SYSRESET=y +CONFIG_SYSRESET_SC5XX=y CONFIG_SPL_TIMER=y CONFIG_USB=y CONFIG_USB_MUSB_HOST=y diff --git a/configs/sc589-mini_defconfig b/configs/sc589-mini_defconfig index 3ecdee918924..8a72e8588456 100644 --- a/configs/sc589-mini_defconfig +++ b/configs/sc589-mini_defconfig @@ -81,6 +81,8 @@ CONFIG_SPECIFY_CONSOLE_INDEX=y CONFIG_SPI=y CONFIG_DM_SPI=y CONFIG_ADI_SPI3=y +CONFIG_SYSRESET=y +CONFIG_SYSRESET_SC5XX=y CONFIG_SPL_TIMER=y CONFIG_USB=y CONFIG_USB_MUSB_HOST=y diff --git a/configs/sc594-som-ezkit-spl_defconfig b/configs/sc594-som-ezkit-spl_defconfig index 0cbce440e014..490d6016166b 100644 --- a/configs/sc594-som-ezkit-spl_defconfig +++ b/configs/sc594-som-ezkit-spl_defconfig @@ -71,6 +71,8 @@ CONFIG_SPI=y CONFIG_DM_SPI=y CONFIG_ADI_SPI3=y CONFIG_CADENCE_QSPI=y +CONFIG_SYSRESET=y +CONFIG_SYSRESET_SC5XX=y CONFIG_SPL_TIMER=y CONFIG_USB=y CONFIG_USB_DWC2=y diff --git a/configs/sc594-som-ezlite-spl_defconfig b/configs/sc594-som-ezlite-spl_defconfig index 34f9c65ebe08..97730cec7ced 100644 --- a/configs/sc594-som-ezlite-spl_defconfig +++ b/configs/sc594-som-ezlite-spl_defconfig @@ -78,6 +78,8 @@ CONFIG_SPI=y CONFIG_DM_SPI=y CONFIG_ADI_SPI3=y CONFIG_CADENCE_QSPI=y +CONFIG_SYSRESET=y +CONFIG_SYSRESET_SC5XX=y CONFIG_SPL_TIMER=y CONFIG_USB=y CONFIG_USB_DWC2=y diff --git a/configs/sc598-htol-spl_defconfig b/configs/sc598-htol-spl_defconfig index e798af87ed20..1d3acd0061b5 100644 --- a/configs/sc598-htol-spl_defconfig +++ b/configs/sc598-htol-spl_defconfig @@ -46,7 +46,6 @@ CONFIG_CMD_GPT=y CONFIG_CMD_MMC=y CONFIG_CMD_MTD=y # CONFIG_CMD_PINMUX is not set -CONFIG_CMD_REMOTEPROC=y CONFIG_CMD_SPI=y CONFIG_DEFAULT_SPI_BUS=2 CONFIG_CMD_USB=y @@ -68,7 +67,6 @@ CONFIG_NET_RETRY_COUNT=20 CONFIG_NETCONSOLE=y CONFIG_IP_DEFRAG=y CONFIG_REGMAP=y -CONFIG_SYSCON=y CONFIG_DMA=y CONFIG_DMA_CHANNELS=y CONFIG_ADI_DMA=y @@ -99,11 +97,12 @@ CONFIG_PINCTRL=y # CONFIG_PINCTRL_GENERIC is not set CONFIG_SPL_PINCTRL=y # CONFIG_SPL_PINCTRL_GENERIC is not set -CONFIG_REMOTEPROC_ADI_SC5XX=y CONFIG_SPI=y CONFIG_DM_SPI=y CONFIG_ADI_SPI3=y CONFIG_CADENCE_QSPI=y +CONFIG_SYSRESET=y +CONFIG_SYSRESET_SC5XX=y CONFIG_SPL_TIMER=y CONFIG_USB=y CONFIG_USB_DWC2=y diff --git a/configs/sc598-som-ezkit-spl_defconfig b/configs/sc598-som-ezkit-spl_defconfig index a1a200092a16..e0ab2aed67f7 100644 --- a/configs/sc598-som-ezkit-spl_defconfig +++ b/configs/sc598-som-ezkit-spl_defconfig @@ -45,7 +45,6 @@ CONFIG_CMD_GPT=y CONFIG_CMD_MMC=y CONFIG_CMD_MTD=y # CONFIG_CMD_PINMUX is not set -CONFIG_CMD_REMOTEPROC=y CONFIG_CMD_SPI=y CONFIG_DEFAULT_SPI_BUS=2 CONFIG_CMD_USB=y @@ -67,7 +66,6 @@ CONFIG_NET_RETRY_COUNT=20 CONFIG_NETCONSOLE=y CONFIG_IP_DEFRAG=y CONFIG_REGMAP=y -CONFIG_SYSCON=y CONFIG_DMA=y CONFIG_DMA_CHANNELS=y CONFIG_ADI_DMA=y @@ -98,11 +96,12 @@ CONFIG_PINCTRL=y # CONFIG_PINCTRL_GENERIC is not set CONFIG_SPL_PINCTRL=y # CONFIG_SPL_PINCTRL_GENERIC is not set -CONFIG_REMOTEPROC_ADI_SC5XX=y CONFIG_SPI=y CONFIG_DM_SPI=y CONFIG_ADI_SPI3=y CONFIG_CADENCE_QSPI=y +CONFIG_SYSRESET=y +CONFIG_SYSRESET_SC5XX=y CONFIG_SPL_TIMER=y CONFIG_USB=y CONFIG_USB_DWC2=y diff --git a/configs/sc598-som-ezlite-spl_defconfig b/configs/sc598-som-ezlite-spl_defconfig index b96ae6d33fcc..618430807b69 100644 --- a/configs/sc598-som-ezlite-spl_defconfig +++ b/configs/sc598-som-ezlite-spl_defconfig @@ -45,7 +45,6 @@ CONFIG_CMD_GPT=y CONFIG_CMD_MMC=y CONFIG_CMD_MTD=y # CONFIG_CMD_PINMUX is not set -CONFIG_CMD_REMOTEPROC=y CONFIG_CMD_SPI=y CONFIG_DEFAULT_SPI_BUS=2 CONFIG_CMD_USB=y @@ -66,7 +65,6 @@ CONFIG_NET_RETRY_COUNT=20 CONFIG_NETCONSOLE=y CONFIG_IP_DEFRAG=y CONFIG_REGMAP=y -CONFIG_SYSCON=y CONFIG_DMA=y CONFIG_DMA_CHANNELS=y CONFIG_ADI_DMA=y @@ -96,11 +94,12 @@ CONFIG_PINCTRL=y # CONFIG_PINCTRL_GENERIC is not set CONFIG_SPL_PINCTRL=y # CONFIG_SPL_PINCTRL_GENERIC is not set -CONFIG_REMOTEPROC_ADI_SC5XX=y CONFIG_SPI=y CONFIG_DM_SPI=y CONFIG_ADI_SPI3=y CONFIG_CADENCE_QSPI=y +CONFIG_SYSRESET=y +CONFIG_SYSRESET_SC5XX=y CONFIG_SPL_TIMER=y CONFIG_USB=y CONFIG_USB_DWC2=y diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index 7100b64bf22a..befdc0c53dd8 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -224,6 +224,17 @@ static int spi_flash_std_remove(struct udevice *dev) struct spi_flash *flash = dev_get_uclass_priv(dev); int ret; +#if !CONFIG_IS_ENABLED(SPI_FLASH_TINY) + if (flash->addr_width == 4 && + !(flash->info->flags & SPI_NOR_OCTAL_DTR_READ) && + (JEDEC_MFR(flash->info) != SNOR_MFR_SPANSION) && + !(flash->flags & SPI_NOR_4B_OPCODES)) { + ret = spi_nor_set_4byte(flash, flash->info, 0); + if (ret) + return ret; + } +#endif + if (CONFIG_IS_ENABLED(SPI_DIRMAP)) { spi_mem_dirmap_destroy(flash->dirmap.wdesc); spi_mem_dirmap_destroy(flash->dirmap.rdesc); diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c index 76c33b243682..b8e53faf01d0 100644 --- a/drivers/mtd/spi/spi-nor-core.c +++ b/drivers/mtd/spi/spi-nor-core.c @@ -742,8 +742,7 @@ static void spi_nor_set_4byte_opcodes(struct spi_nor *nor, #endif /* !CONFIG_IS_ENABLED(SPI_FLASH_BAR) */ /* Enable/disable 4-byte addressing mode. */ -static int set_4byte(struct spi_nor *nor, const struct flash_info *info, - int enable) +int spi_nor_set_4byte(struct spi_nor *nor, const struct flash_info *info, int enable) { int status; bool need_wren = false; @@ -767,11 +766,17 @@ static int set_4byte(struct spi_nor *nor, const struct flash_info *info, write_disable(nor); if (!status && !enable && - JEDEC_MFR(info) == SNOR_MFR_WINBOND) { + (JEDEC_MFR(info) == SNOR_MFR_WINBOND || + JEDEC_MFR(info) == SNOR_MFR_ISSI)) { /* * On Winbond W25Q256FV, leaving 4byte mode causes * the Extended Address Register to be set to 1, so all * 3-byte-address reads come from the second 16M. + * + * On IS25LP01G (and similar ISSI parts), EX4B alone does + * not reliably exit 4-byte address mode; the Extended + * Address Register EXTADD bit (bit 7) stays set. + * * We must clear the register to enable normal behavior. */ write_enable(nor); @@ -3898,7 +3903,7 @@ static int s25_s28_post_bfpt_fixup(struct spi_nor *nor, */ if (params->size > SZ_128M) { if (bfpt->dwords[BFPT_DWORD(16)] & BFPT_DWORD16_EX4B_PWRCYC) { - ret = set_4byte(nor, nor->info, 1); + ret = spi_nor_set_4byte(nor, nor->info, 1); if (ret) return ret; } @@ -4347,7 +4352,7 @@ static int spi_nor_init(struct spi_nor *nor) */ if (nor->flags & SNOR_F_BROKEN_RESET) debug("enabling reset hack; may not recover from unexpected reboots\n"); - set_4byte(nor, nor->info, 1); + spi_nor_set_4byte(nor, nor->info, 1); } return 0; diff --git a/drivers/sysreset/Kconfig b/drivers/sysreset/Kconfig index 67edf004205c..f18039ae23c1 100644 --- a/drivers/sysreset/Kconfig +++ b/drivers/sysreset/Kconfig @@ -151,6 +151,13 @@ config SYSRESET_OCTEON This enables the system reset driver support for Marvell Octeon SoCs. +config SYSRESET_SC5XX + bool "Enable support for Analog Devices SC5xx System Reset" + depends on ARCH_SC5XX + help + Enable system reset support for Analog Devices SC5xx SoCs. + Uses the RCU (Reset Control Unit) SYSRST bit. + config SYSRESET_AT91 bool "Enable support for Microchip/Atmel reset driver" depends on ARCH_AT91 diff --git a/drivers/sysreset/Makefile b/drivers/sysreset/Makefile index f5c78b258961..c697711c2ea9 100644 --- a/drivers/sysreset/Makefile +++ b/drivers/sysreset/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_$(PHASE_)SYSRESET_MAX8907) += sysreset_max8907.o obj-$(CONFIG_SYSRESET_MPC83XX) += sysreset_mpc83xx.o obj-$(CONFIG_SYSRESET_MICROBLAZE) += sysreset_microblaze.o obj-$(CONFIG_SYSRESET_OCTEON) += sysreset_octeon.o +obj-$(CONFIG_SYSRESET_SC5XX) += sysreset_sc5xx.o obj-$(CONFIG_$(PHASE_)SYSRESET_PALMAS) += sysreset_palmas.o obj-$(CONFIG_SYSRESET_PSCI) += sysreset_psci.o obj-$(CONFIG_SYSRESET_SBI) += sysreset_sbi.o diff --git a/drivers/sysreset/sysreset-uclass.c b/drivers/sysreset/sysreset-uclass.c index 536ac7271427..8b5ca7f12360 100644 --- a/drivers/sysreset/sysreset-uclass.c +++ b/drivers/sysreset/sysreset-uclass.c @@ -26,9 +26,19 @@ int sysreset_request(struct udevice *dev, enum sysreset_t type) { struct sysreset_ops *ops = sysreset_get_ops(dev); + struct udevice *flash; + struct uclass *uc; + if (!ops->request) return -ENOSYS; + /* + * Remove SPI flash devices before reset so they can exit 4-byte + * addressing mode. + */ + uclass_id_foreach_dev(UCLASS_SPI_FLASH, flash, uc) + device_remove(flash, DM_REMOVE_NORMAL); + return ops->request(dev, type); } diff --git a/drivers/sysreset/sysreset_sc5xx.c b/drivers/sysreset/sysreset_sc5xx.c new file mode 100644 index 000000000000..7737a28083c9 --- /dev/null +++ b/drivers/sysreset/sysreset_sc5xx.c @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (C) Copyright 2026 - Analog Devices, Inc. + */ + +#include +#include +#include + +struct sc5xx_sysreset_priv { + void __iomem *rcu; +}; + +static int sc5xx_sysreset_request(struct udevice *dev, enum sysreset_t type) +{ + struct sc5xx_sysreset_priv *priv = dev_get_priv(dev); + + writel(readl(priv->rcu) | 1, priv->rcu); + return -EINPROGRESS; +} + +static int sc5xx_sysreset_probe(struct udevice *dev) +{ + struct sc5xx_sysreset_priv *priv = dev_get_priv(dev); + + priv->rcu = dev_remap_addr(dev); + if (!priv->rcu) + return -EINVAL; + return 0; +} + +static const struct udevice_id sc5xx_sysreset_ids[] = { + { .compatible = "adi,reset-controller" }, + { } +}; + +static struct sysreset_ops sc5xx_sysreset_ops = { + .request = sc5xx_sysreset_request, +}; + +U_BOOT_DRIVER(sysreset_sc5xx) = { + .name = "sc5xx_sysreset", + .id = UCLASS_SYSRESET, + .of_match = sc5xx_sysreset_ids, + .ops = &sc5xx_sysreset_ops, + .probe = sc5xx_sysreset_probe, + .priv_auto = sizeof(struct sc5xx_sysreset_priv), +}; diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 4eef4ab04883..0b335484560a 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -668,6 +668,16 @@ static inline int spi_nor_remove(struct spi_nor *nor) * Return: 0 for success, -errno for failure. */ int spi_nor_remove(struct spi_nor *nor); + +/** + * spi_nor_set_4byte() - perform cleanup before booting to the next stage + * @nor: the spi_nor structure + * @flash_info: the flash_info structure + * @enable: enable or disable 4byte mode + * + * Return: 0 for success, -errno for failure. + */ +int spi_nor_set_4byte(struct spi_nor *nor, const struct flash_info *info, int enable); #endif #endif