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