summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2019-11-01 17:49:40 -0400
committerTom Rini <trini@konsulko.com>2019-11-01 17:49:40 -0400
commit61e8f2985bd977775d864e44f7807fd1932192e5 (patch)
tree9c1cd4d0a92f0528b6aa7095468d397637b6b048 /drivers
parent5d6f05352b69d4858a2a9e9136ac3a734f0222bb (diff)
parent3f6b4ea225656b41613fd538925e29141f22c4a7 (diff)
downloadu-boot-61e8f2985bd977775d864e44f7807fd1932192e5.tar.gz
Merge tag 'arc-fixes-for-2020.01-rc2' of https://gitlab.denx.de/u-boot/custodians/u-boot-arc
ARC fixes for v2020.01-rc2 The main change is move to DM_MMC of yet 2 another ARC boards: AXS101 & IoTDK. Among that we improve handling of stock-formatted SD-cards of high volume on EM SDP as well as introduction of reset driver for HSDK which is required for prepser reinitialization of some peripherals like USB etc.
Diffstat (limited to 'drivers')
-rw-r--r--drivers/reset/Kconfig7
-rw-r--r--drivers/reset/Makefile1
-rw-r--r--drivers/reset/reset-hsdk.c116
3 files changed, 124 insertions, 0 deletions
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index cff00820e4..75ccd65799 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -91,6 +91,13 @@ config RESET_ROCKCHIP
though is that some reset signals, like I2C or MISC reset multiple
devices.
+config RESET_HSDK
+ bool "Synopsys HSDK Reset Driver"
+ depends on DM_RESET && TARGET_HSDK
+ default y
+ help
+ This enables the reset controller driver for HSDK board.
+
config RESET_MESON
bool "Reset controller driver for Amlogic Meson SoCs"
depends on DM_RESET && ARCH_MESON
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 8102d8db29..0a044d5d8c 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_STM32_RESET) += stm32-reset.o
obj-$(CONFIG_TEGRA_CAR_RESET) += tegra-car-reset.o
obj-$(CONFIG_TEGRA186_RESET) += tegra186-reset.o
obj-$(CONFIG_RESET_TI_SCI) += reset-ti-sci.o
+obj-$(CONFIG_RESET_HSDK) += reset-hsdk.o
obj-$(CONFIG_RESET_BCM6345) += reset-bcm6345.o
obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
obj-$(CONFIG_AST2500_RESET) += ast2500-reset.o
diff --git a/drivers/reset/reset-hsdk.c b/drivers/reset/reset-hsdk.c
new file mode 100644
index 0000000000..213d6c87be
--- /dev/null
+++ b/drivers/reset/reset-hsdk.c
@@ -0,0 +1,116 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * HSDK SoC Reset Controller driver
+ *
+ * Copyright (C) 2019 Synopsys, Inc. All rights reserved.
+ * Author: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
+ */
+
+#include <asm/io.h>
+#include <common.h>
+#include <dm.h>
+#include <linux/iopoll.h>
+#include <reset-uclass.h>
+
+struct hsdk_rst {
+ void __iomem *regs_ctl;
+ void __iomem *regs_rst;
+};
+
+static const u32 rst_map[] = {
+ BIT(16), /* APB_RST */
+ BIT(17), /* AXI_RST */
+ BIT(18), /* ETH_RST */
+ BIT(19), /* USB_RST */
+ BIT(20), /* SDIO_RST */
+ BIT(21), /* HDMI_RST */
+ BIT(22), /* GFX_RST */
+ BIT(25), /* DMAC_RST */
+ BIT(31), /* EBI_RST */
+};
+
+#define HSDK_MAX_RESETS ARRAY_SIZE(rst_map)
+
+#define CGU_SYS_RST_CTRL 0x0
+#define CGU_IP_SW_RESET 0x0
+#define CGU_IP_SW_RESET_DELAY_SHIFT 16
+#define CGU_IP_SW_RESET_DELAY_MASK GENMASK(31, CGU_IP_SW_RESET_DELAY_SHIFT)
+#define CGU_IP_SW_RESET_DELAY 0
+#define CGU_IP_SW_RESET_RESET BIT(0)
+#define SW_RESET_TIMEOUT 10000
+
+static void hsdk_reset_config(struct hsdk_rst *rst, unsigned long id)
+{
+ writel(rst_map[id], rst->regs_ctl + CGU_SYS_RST_CTRL);
+}
+
+static int hsdk_reset_do(struct hsdk_rst *rst)
+{
+ u32 reg;
+
+ reg = readl(rst->regs_rst + CGU_IP_SW_RESET);
+ reg &= ~CGU_IP_SW_RESET_DELAY_MASK;
+ reg |= CGU_IP_SW_RESET_DELAY << CGU_IP_SW_RESET_DELAY_SHIFT;
+ reg |= CGU_IP_SW_RESET_RESET;
+ writel(reg, rst->regs_rst + CGU_IP_SW_RESET);
+
+ /* wait till reset bit is back to 0 */
+ return readl_poll_timeout(rst->regs_rst + CGU_IP_SW_RESET, reg,
+ !(reg & CGU_IP_SW_RESET_RESET), SW_RESET_TIMEOUT);
+}
+
+static int hsdk_reset_reset(struct reset_ctl *rst_ctl)
+{
+ struct udevice *dev = rst_ctl->dev;
+ struct hsdk_rst *rst = dev_get_priv(dev);
+
+ if (rst_ctl->id >= HSDK_MAX_RESETS)
+ return -EINVAL;
+
+ debug("%s(reset_ctl=%p) (dev=%p, id=%lu)\n", __func__, rst_ctl,
+ rst_ctl->dev, rst_ctl->id);
+
+ hsdk_reset_config(rst, rst_ctl->id);
+ return hsdk_reset_do(rst);
+}
+
+static int hsdk_reset_noop(struct reset_ctl *rst_ctl)
+{
+ return 0;
+}
+
+static const struct reset_ops hsdk_reset_ops = {
+ .request = hsdk_reset_noop,
+ .free = hsdk_reset_noop,
+ .rst_assert = hsdk_reset_noop,
+ .rst_deassert = hsdk_reset_reset,
+};
+
+static const struct udevice_id hsdk_reset_dt_match[] = {
+ { .compatible = "snps,hsdk-reset" },
+ { },
+};
+
+static int hsdk_reset_probe(struct udevice *dev)
+{
+ struct hsdk_rst *rst = dev_get_priv(dev);
+
+ rst->regs_ctl = dev_remap_addr_index(dev, 0);
+ if (!rst->regs_ctl)
+ return -EINVAL;
+
+ rst->regs_rst = dev_remap_addr_index(dev, 1);
+ if (!rst->regs_rst)
+ return -EINVAL;
+
+ return 0;
+}
+
+U_BOOT_DRIVER(hsdk_reset) = {
+ .name = "hsdk-reset",
+ .id = UCLASS_RESET,
+ .of_match = hsdk_reset_dt_match,
+ .ops = &hsdk_reset_ops,
+ .probe = hsdk_reset_probe,
+ .priv_auto_alloc_size = sizeof(struct hsdk_rst),
+};