Commit 858d4976293f0b3d72e5dcf0e8a1a973efafeee3

Authored by maxims@google.com
Committed by Tom Rini
1 parent 413353b30b

aspeed: Reset Driver

Add Reset Driver for ast2500 SoC. This driver uses Watchdog Timer to
perform resets and thus depends on it. The actual Watchdog device used
needs to be configured in Device Tree using "aspeed,wdt" property, which
must be WDT phandle, for example:

rst: reset-controller {
    compatible = "aspeed,ast2500-reset";
    aspeed,wdt = <&wdt1>;
}

Signed-off-by: Maxim Sloyko <maxims@google.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

Showing 4 changed files with 145 additions and 0 deletions Side-by-side Diff

arch/arm/include/asm/arch-aspeed/scu_ast2500.h
... ... @@ -31,6 +31,34 @@
31 31  
32 32 #define SCU_MISC_UARTCLK_DIV13 (1 << 12)
33 33  
  34 +/*
  35 + * SYSRESET is actually more like a Power register,
  36 + * except that corresponding bit set to 1 means that
  37 + * the peripheral is off.
  38 + */
  39 +#define SCU_SYSRESET_XDMA (1 << 25)
  40 +#define SCU_SYSRESET_MCTP (1 << 24)
  41 +#define SCU_SYSRESET_ADC (1 << 23)
  42 +#define SCU_SYSRESET_JTAG (1 << 22)
  43 +#define SCU_SYSRESET_MIC (1 << 18)
  44 +#define SCU_SYSRESET_SDIO (1 << 16)
  45 +#define SCU_SYSRESET_USB11HOST (1 << 15)
  46 +#define SCU_SYSRESET_USBHUB (1 << 14)
  47 +#define SCU_SYSRESET_CRT (1 << 13)
  48 +#define SCU_SYSRESET_MAC2 (1 << 12)
  49 +#define SCU_SYSRESET_MAC1 (1 << 11)
  50 +#define SCU_SYSRESET_PECI (1 << 10)
  51 +#define SCU_SYSRESET_PWM (1 << 9)
  52 +#define SCU_SYSRESET_PCI_VGA (1 << 8)
  53 +#define SCU_SYSRESET_2D (1 << 7)
  54 +#define SCU_SYSRESET_VIDEO (1 << 6)
  55 +#define SCU_SYSRESET_LPC (1 << 5)
  56 +#define SCU_SYSRESET_HAC (1 << 4)
  57 +#define SCU_SYSRESET_USBHID (1 << 3)
  58 +#define SCU_SYSRESET_I2C (1 << 2)
  59 +#define SCU_SYSRESET_AHB (1 << 1)
  60 +#define SCU_SYSRESET_SDRAM_WDT (1 << 0)
  61 +
34 62 #ifndef __ASSEMBLY__
35 63  
36 64 struct ast2500_clk_priv {
drivers/reset/Kconfig
... ... @@ -51,5 +51,15 @@
51 51 Say Y if you want to control reset signals provided by System Control
52 52 block, Media I/O block, Peripheral Block.
53 53  
  54 +config AST2500_RESET
  55 + bool "Reset controller driver for AST2500 SoCs"
  56 + depends on DM_RESET && WDT_ASPEED
  57 + default y if ASPEED_AST2500
  58 + help
  59 + Support for reset controller on AST2500 SoC. This controller uses
  60 + watchdog to reset different peripherals and thus only supports
  61 + resets that are supported by watchdog. The main limitation though
  62 + is that some reset signals, like I2C or MISC reset multiple devices.
  63 +
54 64 endmenu
drivers/reset/Makefile
... ... @@ -9,4 +9,5 @@
9 9 obj-$(CONFIG_TEGRA_CAR_RESET) += tegra-car-reset.o
10 10 obj-$(CONFIG_TEGRA186_RESET) += tegra186-reset.o
11 11 obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
  12 +obj-$(CONFIG_AST2500_RESET) += ast2500-reset.o
drivers/reset/ast2500-reset.c
  1 +/*
  2 + * Copyright 2017 Google, Inc
  3 + *
  4 + * SPDX-License-Identifier: GPL-2.0
  5 + */
  6 +
  7 +#include <common.h>
  8 +#include <dm.h>
  9 +#include <misc.h>
  10 +#include <reset.h>
  11 +#include <reset-uclass.h>
  12 +#include <wdt.h>
  13 +#include <asm/io.h>
  14 +#include <asm/arch/scu_ast2500.h>
  15 +#include <asm/arch/wdt.h>
  16 +
  17 +DECLARE_GLOBAL_DATA_PTR;
  18 +
  19 +struct ast2500_reset_priv {
  20 + /* WDT used to perform resets. */
  21 + struct udevice *wdt;
  22 + struct ast2500_scu *scu;
  23 +};
  24 +
  25 +static int ast2500_ofdata_to_platdata(struct udevice *dev)
  26 +{
  27 + struct ast2500_reset_priv *priv = dev_get_priv(dev);
  28 + int ret;
  29 +
  30 + ret = uclass_get_device_by_phandle(UCLASS_WDT, dev, "aspeed,wdt",
  31 + &priv->wdt);
  32 + if (ret) {
  33 + debug("%s: can't find WDT for reset controller", __func__);
  34 + return ret;
  35 + }
  36 +
  37 + return 0;
  38 +}
  39 +
  40 +static int ast2500_reset_assert(struct reset_ctl *reset_ctl)
  41 +{
  42 + struct ast2500_reset_priv *priv = dev_get_priv(reset_ctl->dev);
  43 + u32 reset_mode, reset_mask;
  44 + bool reset_sdram;
  45 + int ret;
  46 +
  47 + /*
  48 + * To reset SDRAM, a specifal flag in SYSRESET register
  49 + * needs to be enabled first
  50 + */
  51 + reset_mode = ast_reset_mode_from_flags(reset_ctl->id);
  52 + reset_mask = ast_reset_mask_from_flags(reset_ctl->id);
  53 + reset_sdram = reset_mode == WDT_CTRL_RESET_SOC &&
  54 + (reset_mask & WDT_RESET_SDRAM);
  55 +
  56 + if (reset_sdram) {
  57 + ast_scu_unlock(priv->scu);
  58 + setbits_le32(&priv->scu->sysreset_ctrl1,
  59 + SCU_SYSRESET_SDRAM_WDT);
  60 + ret = wdt_expire_now(priv->wdt, reset_ctl->id);
  61 + clrbits_le32(&priv->scu->sysreset_ctrl1,
  62 + SCU_SYSRESET_SDRAM_WDT);
  63 + ast_scu_lock(priv->scu);
  64 + } else {
  65 + ret = wdt_expire_now(priv->wdt, reset_ctl->id);
  66 + }
  67 +
  68 + return ret;
  69 +}
  70 +
  71 +static int ast2500_reset_request(struct reset_ctl *reset_ctl)
  72 +{
  73 + debug("%s(reset_ctl=%p) (dev=%p, id=%lu)\n", __func__, reset_ctl,
  74 + reset_ctl->dev, reset_ctl->id);
  75 +
  76 + return 0;
  77 +}
  78 +
  79 +static int ast2500_reset_probe(struct udevice *dev)
  80 +{
  81 + struct ast2500_reset_priv *priv = dev_get_priv(dev);
  82 +
  83 + priv->scu = ast_get_scu();
  84 +
  85 + return 0;
  86 +}
  87 +
  88 +static const struct udevice_id ast2500_reset_ids[] = {
  89 + { .compatible = "aspeed,ast2500-reset" },
  90 + { }
  91 +};
  92 +
  93 +struct reset_ops ast2500_reset_ops = {
  94 + .rst_assert = ast2500_reset_assert,
  95 + .request = ast2500_reset_request,
  96 +};
  97 +
  98 +U_BOOT_DRIVER(ast2500_reset) = {
  99 + .name = "ast2500_reset",
  100 + .id = UCLASS_RESET,
  101 + .of_match = ast2500_reset_ids,
  102 + .probe = ast2500_reset_probe,
  103 + .ops = &ast2500_reset_ops,
  104 + .ofdata_to_platdata = ast2500_ofdata_to_platdata,
  105 + .priv_auto_alloc_size = sizeof(struct ast2500_reset_priv),
  106 +};