blob: a9f052a0c56e7014d3ff211b2cfcad19bbe42c01 [file] [log] [blame]
Shawn Guo8aa8f302019-03-20 15:32:39 +08001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2019, Linaro Limited
4 */
5
6#include <asm/io.h>
7#include <common.h>
8#include <dm.h>
9#include <dt-bindings/reset/ti-syscon.h>
10#include <reset-uclass.h>
11
12struct hisi_reset_priv {
13 void __iomem *base;
14};
15
16static int hisi_reset_deassert(struct reset_ctl *rst)
17{
18 struct hisi_reset_priv *priv = dev_get_priv(rst->dev);
19 u32 val;
20
21 val = readl(priv->base + rst->data);
22 if (rst->polarity & DEASSERT_SET)
23 val |= BIT(rst->id);
24 else
25 val &= ~BIT(rst->id);
26 writel(val, priv->base + rst->data);
27
28 return 0;
29}
30
31static int hisi_reset_assert(struct reset_ctl *rst)
32{
33 struct hisi_reset_priv *priv = dev_get_priv(rst->dev);
34 u32 val;
35
36 val = readl(priv->base + rst->data);
37 if (rst->polarity & ASSERT_SET)
38 val |= BIT(rst->id);
39 else
40 val &= ~BIT(rst->id);
41 writel(val, priv->base + rst->data);
42
43 return 0;
44}
45
46static int hisi_reset_free(struct reset_ctl *rst)
47{
48 return 0;
49}
50
51static int hisi_reset_request(struct reset_ctl *rst)
52{
53 return 0;
54}
55
56static int hisi_reset_of_xlate(struct reset_ctl *rst,
57 struct ofnode_phandle_args *args)
58{
59 if (args->args_count != 3) {
60 debug("Invalid args_count: %d\n", args->args_count);
61 return -EINVAL;
62 }
63
64 /* Use .data field as register offset and .id field as bit shift */
65 rst->data = args->args[0];
66 rst->id = args->args[1];
67 rst->polarity = args->args[2];
68
69 return 0;
70}
71
72static const struct reset_ops hisi_reset_reset_ops = {
73 .of_xlate = hisi_reset_of_xlate,
74 .request = hisi_reset_request,
75 .free = hisi_reset_free,
76 .rst_assert = hisi_reset_assert,
77 .rst_deassert = hisi_reset_deassert,
78};
79
80static const struct udevice_id hisi_reset_ids[] = {
81 { .compatible = "hisilicon,hi3798cv200-reset" },
82 { }
83};
84
85static int hisi_reset_probe(struct udevice *dev)
86{
87 struct hisi_reset_priv *priv = dev_get_priv(dev);
88
89 priv->base = dev_remap_addr(dev);
90 if (!priv->base)
91 return -ENOMEM;
92
93 return 0;
94}
95
96U_BOOT_DRIVER(hisi_reset) = {
97 .name = "hisilicon_reset",
98 .id = UCLASS_RESET,
99 .of_match = hisi_reset_ids,
100 .ops = &hisi_reset_reset_ops,
101 .probe = hisi_reset_probe,
102 .priv_auto_alloc_size = sizeof(struct hisi_reset_priv),
103};