uboot/drivers/reset/reset-hsdk.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * HSDK SoC Reset Controller driver
   4 *
   5 * Copyright (C) 2019 Synopsys, Inc. All rights reserved.
   6 * Author: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
   7 */
   8
   9#include <log.h>
  10#include <asm/io.h>
  11#include <common.h>
  12#include <dm.h>
  13#include <linux/bitops.h>
  14#include <linux/iopoll.h>
  15#include <reset-uclass.h>
  16
  17struct hsdk_rst {
  18        void __iomem            *regs_ctl;
  19        void __iomem            *regs_rst;
  20};
  21
  22static const u32 rst_map[] = {
  23        BIT(16), /* APB_RST  */
  24        BIT(17), /* AXI_RST  */
  25        BIT(18), /* ETH_RST  */
  26        BIT(19), /* USB_RST  */
  27        BIT(20), /* SDIO_RST */
  28        BIT(21), /* HDMI_RST */
  29        BIT(22), /* GFX_RST  */
  30        BIT(25), /* DMAC_RST */
  31        BIT(31), /* EBI_RST  */
  32};
  33
  34#define HSDK_MAX_RESETS                 ARRAY_SIZE(rst_map)
  35
  36#define CGU_SYS_RST_CTRL                0x0
  37#define CGU_IP_SW_RESET                 0x0
  38#define CGU_IP_SW_RESET_DELAY_SHIFT     16
  39#define CGU_IP_SW_RESET_DELAY_MASK      GENMASK(31, CGU_IP_SW_RESET_DELAY_SHIFT)
  40#define CGU_IP_SW_RESET_DELAY           0
  41#define CGU_IP_SW_RESET_RESET           BIT(0)
  42#define SW_RESET_TIMEOUT                10000
  43
  44static void hsdk_reset_config(struct hsdk_rst *rst, unsigned long id)
  45{
  46        writel(rst_map[id], rst->regs_ctl + CGU_SYS_RST_CTRL);
  47}
  48
  49static int hsdk_reset_do(struct hsdk_rst *rst)
  50{
  51        u32 reg;
  52
  53        reg = readl(rst->regs_rst + CGU_IP_SW_RESET);
  54        reg &= ~CGU_IP_SW_RESET_DELAY_MASK;
  55        reg |= CGU_IP_SW_RESET_DELAY << CGU_IP_SW_RESET_DELAY_SHIFT;
  56        reg |= CGU_IP_SW_RESET_RESET;
  57        writel(reg, rst->regs_rst + CGU_IP_SW_RESET);
  58
  59        /* wait till reset bit is back to 0 */
  60        return readl_poll_timeout(rst->regs_rst + CGU_IP_SW_RESET, reg,
  61                !(reg & CGU_IP_SW_RESET_RESET), SW_RESET_TIMEOUT);
  62}
  63
  64static int hsdk_reset_reset(struct reset_ctl *rst_ctl)
  65{
  66        struct udevice *dev = rst_ctl->dev;
  67        struct hsdk_rst *rst = dev_get_priv(dev);
  68
  69        if (rst_ctl->id >= HSDK_MAX_RESETS)
  70                return -EINVAL;
  71
  72        debug("%s(reset_ctl=%p) (dev=%p, id=%lu)\n", __func__, rst_ctl,
  73              rst_ctl->dev, rst_ctl->id);
  74
  75        hsdk_reset_config(rst, rst_ctl->id);
  76        return hsdk_reset_do(rst);
  77}
  78
  79static int hsdk_reset_noop(struct reset_ctl *rst_ctl)
  80{
  81        return 0;
  82}
  83
  84static const struct reset_ops hsdk_reset_ops = {
  85        .request        = hsdk_reset_noop,
  86        .rfree          = hsdk_reset_noop,
  87        .rst_assert     = hsdk_reset_noop,
  88        .rst_deassert   = hsdk_reset_reset,
  89};
  90
  91static const struct udevice_id hsdk_reset_dt_match[] = {
  92        { .compatible = "snps,hsdk-reset" },
  93        { },
  94};
  95
  96static int hsdk_reset_probe(struct udevice *dev)
  97{
  98        struct hsdk_rst *rst = dev_get_priv(dev);
  99
 100        rst->regs_ctl = dev_remap_addr_index(dev, 0);
 101        if (!rst->regs_ctl)
 102                return -EINVAL;
 103
 104        rst->regs_rst = dev_remap_addr_index(dev, 1);
 105        if (!rst->regs_rst)
 106                return -EINVAL;
 107
 108        return 0;
 109}
 110
 111U_BOOT_DRIVER(hsdk_reset) = {
 112        .name = "hsdk-reset",
 113        .id = UCLASS_RESET,
 114        .of_match = hsdk_reset_dt_match,
 115        .ops = &hsdk_reset_ops,
 116        .probe = hsdk_reset_probe,
 117        .priv_auto      = sizeof(struct hsdk_rst),
 118};
 119