1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) ASPEED Technology Inc.
4 */
5
6 #include <common.h>
7 #include <dm.h>
8 #include <misc.h>
9 #include <reset.h>
10 #include <reset-uclass.h>
11 #include <wdt.h>
12 #include <asm/io.h>
13 #include <asm/arch/scu_ast2600.h>
14
15 struct ast2600_reset_priv {
16 /* WDT used to perform resets. */
17 struct udevice *wdt;
18 struct ast2600_scu *scu;
19 };
20
ast2600_reset_deassert(struct reset_ctl * reset_ctl)21 static int ast2600_reset_deassert(struct reset_ctl *reset_ctl)
22 {
23 struct ast2600_reset_priv *priv = dev_get_priv(reset_ctl->dev);
24 struct ast2600_scu *scu = priv->scu;
25
26 debug("ast2600_reset_assert reset_ctl->id %ld \n", reset_ctl->id);
27
28 if(reset_ctl->id >= 32)
29 writel(BIT(reset_ctl->id - 32), &scu->sysreset_clr_ctrl2);
30 else
31 writel(BIT(reset_ctl->id), &scu->sysreset_clr_ctrl1);
32
33 return 0;
34 }
35
ast2600_reset_assert(struct reset_ctl * reset_ctl)36 static int ast2600_reset_assert(struct reset_ctl *reset_ctl)
37 {
38 struct ast2600_reset_priv *priv = dev_get_priv(reset_ctl->dev);
39 struct ast2600_scu *scu = priv->scu;
40
41 debug("ast2600_reset_assert reset_ctl->id %ld \n", reset_ctl->id);
42
43 if(reset_ctl->id >= 32)
44 writel(BIT(reset_ctl->id - 32), &scu->sysreset_ctrl2);
45 else
46 writel(BIT(reset_ctl->id), &scu->sysreset_ctrl1);
47
48 return 0;
49 }
50
ast2600_reset_request(struct reset_ctl * reset_ctl)51 static int ast2600_reset_request(struct reset_ctl *reset_ctl)
52 {
53 debug("%s(reset_ctl=%p) (dev=%p, id=%lu)\n", __func__, reset_ctl,
54 reset_ctl->dev, reset_ctl->id);
55
56 return 0;
57 }
58
ast2600_reset_probe(struct udevice * dev)59 static int ast2600_reset_probe(struct udevice *dev)
60 {
61 struct ast2600_reset_priv *priv = dev_get_priv(dev);
62 struct udevice *clk_dev;
63 int ret = 0;
64
65 /* find SCU base address from clock device */
66 ret = uclass_get_device_by_driver(UCLASS_CLK, DM_GET_DRIVER(aspeed_scu),
67 &clk_dev);
68 if (ret) {
69 debug("clock device not found\n");
70 return ret;
71 }
72
73 priv->scu = devfdt_get_addr_ptr(clk_dev);
74 if (IS_ERR(priv->scu)) {
75 debug("%s(): can't get SCU\n", __func__);
76 return PTR_ERR(priv->scu);
77 }
78
79 return 0;
80 }
81
ast2600_ofdata_to_platdata(struct udevice * dev)82 static int ast2600_ofdata_to_platdata(struct udevice *dev)
83 {
84 // struct ast2600_reset_priv *priv = dev_get_priv(dev);
85 // int ret;
86
87 #if 0
88 ret = uclass_get_device_by_phandle(UCLASS_WDT, dev, "aspeed,ast2600-wdt",
89 &priv->wdt);
90 if (ret) {
91 printf("%s: can't find WDT for reset controller", __func__);
92 return ret;
93 }
94 #endif
95
96 return 0;
97 }
98
99 static const struct udevice_id aspeed_reset_ids[] = {
100 { .compatible = "aspeed,ast2600-reset" },
101 { }
102 };
103
104 struct reset_ops aspeed_reset_ops = {
105 .rst_assert = ast2600_reset_assert,
106 .rst_deassert = ast2600_reset_deassert,
107 .request = ast2600_reset_request,
108 };
109
110 U_BOOT_DRIVER(aspeed_reset) = {
111 .name = "aspeed_reset",
112 .id = UCLASS_RESET,
113 .of_match = aspeed_reset_ids,
114 .probe = ast2600_reset_probe,
115 .ops = &aspeed_reset_ops,
116 .ofdata_to_platdata = ast2600_ofdata_to_platdata,
117 .priv_auto_alloc_size = sizeof(struct ast2600_reset_priv),
118 };
119