mmc: fsl_esdhc: workaround for hardware 3.3v IO reliability issue
[oweals/u-boot.git] / drivers / reset / reset-hsdk.c
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
17 struct hsdk_rst {
18         void __iomem            *regs_ctl;
19         void __iomem            *regs_rst;
20 };
21
22 static 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
44 static 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
49 static 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
64 static 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
79 static int hsdk_reset_noop(struct reset_ctl *rst_ctl)
80 {
81         return 0;
82 }
83
84 static 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
91 static const struct udevice_id hsdk_reset_dt_match[] = {
92         { .compatible = "snps,hsdk-reset" },
93         { },
94 };
95
96 static 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
111 U_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_alloc_size = sizeof(struct hsdk_rst),
118 };