1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright 2020 ASPEED Technology Inc.
4  */
5 
6 #include <dm.h>
7 #include <log.h>
8 #include <misc.h>
9 #include <reset.h>
10 #include <reset-uclass.h>
11 #include <linux/err.h>
12 #include <asm/io.h>
13 #include <asm/arch/scu_ast2600.h>
14 
15 struct ast2600_reset_priv {
16 	struct ast2600_scu *scu;
17 };
18 
ast2600_reset_assert(struct reset_ctl * reset_ctl)19 static int ast2600_reset_assert(struct reset_ctl *reset_ctl)
20 {
21 	struct ast2600_reset_priv *priv = dev_get_priv(reset_ctl->dev);
22 	struct ast2600_scu *scu = priv->scu;
23 
24 	debug("%s: reset_ctl->id: %lu\n", __func__, reset_ctl->id);
25 
26 	if (reset_ctl->id < 32)
27 		writel(BIT(reset_ctl->id), &scu->modrst_ctrl1);
28 	else
29 		writel(BIT(reset_ctl->id - 32), &scu->modrst_ctrl2);
30 
31 	return 0;
32 }
33 
ast2600_reset_deassert(struct reset_ctl * reset_ctl)34 static int ast2600_reset_deassert(struct reset_ctl *reset_ctl)
35 {
36 	struct ast2600_reset_priv *priv = dev_get_priv(reset_ctl->dev);
37 	struct ast2600_scu *scu = priv->scu;
38 
39 	debug("%s: reset_ctl->id: %lu\n", __func__, reset_ctl->id);
40 
41 	if (reset_ctl->id < 32)
42 		writel(BIT(reset_ctl->id), &scu->modrst_clr1);
43 	else
44 		writel(BIT(reset_ctl->id - 32), &scu->modrst_clr2);
45 
46 	return 0;
47 }
48 
ast2600_reset_status(struct reset_ctl * reset_ctl)49 static int ast2600_reset_status(struct reset_ctl *reset_ctl)
50 {
51 	struct ast2600_reset_priv *priv = dev_get_priv(reset_ctl->dev);
52 	struct ast2600_scu *scu = priv->scu;
53 	int status;
54 
55 	debug("%s: reset_ctl->id: %lu\n", __func__, reset_ctl->id);
56 
57 	if (reset_ctl->id < 32)
58 		status = BIT(reset_ctl->id) & readl(&scu->modrst_ctrl1);
59 	else
60 		status = BIT(reset_ctl->id - 32) & readl(&scu->modrst_ctrl2);
61 
62 	return !!status;
63 }
64 
ast2600_reset_probe(struct udevice * dev)65 static int ast2600_reset_probe(struct udevice *dev)
66 {
67 	int rc;
68 	struct ast2600_reset_priv *priv = dev_get_priv(dev);
69 	struct udevice *scu_dev;
70 
71 	/* get SCU base from clock device */
72 	rc = uclass_get_device_by_driver(UCLASS_CLK,
73 					 DM_DRIVER_GET(aspeed_ast2600_scu), &scu_dev);
74 	if (rc) {
75 		debug("%s: clock device not found, rc=%d\n", __func__, rc);
76 		return rc;
77 	}
78 
79 	priv->scu = devfdt_get_addr_ptr(scu_dev);
80 	if (IS_ERR_OR_NULL(priv->scu)) {
81 		debug("%s: invalid SCU base pointer\n", __func__);
82 		return PTR_ERR(priv->scu);
83 	}
84 
85 	return 0;
86 }
87 
88 static const struct udevice_id ast2600_reset_ids[] = {
89 	{ .compatible = "aspeed,ast2600-reset" },
90 	{ }
91 };
92 
93 struct reset_ops ast2600_reset_ops = {
94 	.rst_assert = ast2600_reset_assert,
95 	.rst_deassert = ast2600_reset_deassert,
96 	.rst_status = ast2600_reset_status,
97 };
98 
99 U_BOOT_DRIVER(ast2600_reset) = {
100 	.name = "ast2600_reset",
101 	.id = UCLASS_RESET,
102 	.of_match = ast2600_reset_ids,
103 	.probe = ast2600_reset_probe,
104 	.ops = &ast2600_reset_ops,
105 	.priv_auto = sizeof(struct ast2600_reset_priv),
106 };
107