blob: a3b85a422508d8c23bb3df67ee7db7e2a2c3db26 [file] [log] [blame]
Jim Liueb08c4b2024-01-03 15:29:33 +08001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright 2023 Nuvoton Technology Corp.
4 */
5
6#include <dm.h>
7#include <reset-uclass.h>
8#include <asm/io.h>
9#include <dm/device_compat.h>
10
11struct npcm_reset_priv {
12 void __iomem *base;
13};
14
15static int npcm_reset_request(struct reset_ctl *rst)
16{
17 return 0;
18}
19
20static int npcm_reset_free(struct reset_ctl *rst)
21{
22 return 0;
23}
24
25static int npcm_reset_assert(struct reset_ctl *rst)
26{
27 struct npcm_reset_priv *priv = dev_get_priv(rst->dev);
28 u32 val;
29
30 debug("%s: id 0x%lx, data %ld\n", __func__, rst->id, rst->data);
31 val = readl(priv->base + rst->id);
32 val |= BIT(rst->data);
33 writel(val, priv->base + rst->id);
34
35 return 0;
36}
37
38static int npcm_reset_deassert(struct reset_ctl *rst)
39{
40 struct npcm_reset_priv *priv = dev_get_priv(rst->dev);
41 u32 val;
42
43 debug("%s: id 0x%lx, data %ld\n", __func__, rst->id, rst->data);
44 val = readl(priv->base + rst->id);
45 val &= ~BIT(rst->data);
46 writel(val, priv->base + rst->id);
47
48 return 0;
49}
50
51static int npcm_reset_xlate(struct reset_ctl *rst,
52 struct ofnode_phandle_args *args)
53{
54 if (args->args_count != 2) {
55 dev_err(rst->dev, "Invalid args_count: %d\n", args->args_count);
56 return -EINVAL;
57 }
58
59 /* Use id field as register offset and data field as reset bit positiion */
60 rst->id = args->args[0];
61 rst->data = args->args[1];
62
63 return 0;
64}
65
66static int npcm_reset_probe(struct udevice *dev)
67{
68 struct npcm_reset_priv *priv = dev_get_priv(dev);
69
70 priv->base = dev_remap_addr(dev);
71 if (!priv->base)
72 return -EINVAL;
73
74 return 0;
75}
76
77static int npcm_reset_bind(struct udevice *dev)
78{
79 void __iomem *reg_base;
80 u32 *rcr_values;
81 int num_fields;
82 u32 reg, val;
83 int ret, i;
84
85 reg_base = dev_remap_addr(dev);
86 if (!reg_base)
87 return -EINVAL;
88
89 /*
90 * Set RCR initial value
91 * The rcr-initial-values cell is <reg_offset val>
92 */
93 num_fields = dev_read_size(dev, "rcr-initial-values");
94 if (num_fields < 2)
95 return 0;
96
97 num_fields /= sizeof(u32);
98 if (num_fields % 2)
99 return -EINVAL;
100
101 num_fields = num_fields / 2;
102 rcr_values = malloc(num_fields * 2 * sizeof(u32));
103 if (!rcr_values)
104 return -ENOMEM;
105
106 ret = dev_read_u32_array(dev, "rcr-initial-values", rcr_values,
107 num_fields * 2);
108 if (ret < 0) {
109 free(rcr_values);
110 return -EINVAL;
111 }
112
113 for (i = 0; i < num_fields; i++) {
114 reg = rcr_values[2 * i];
115 val = rcr_values[2 * i + 1];
116 writel(val, reg_base + reg);
117 }
118 free(rcr_values);
119
120 return 0;
121}
122
123static const struct udevice_id npcm_reset_ids[] = {
124 { .compatible = "nuvoton,npcm845-reset" },
125 { .compatible = "nuvoton,npcm750-reset" },
126 { }
127};
128
129struct reset_ops npcm_reset_ops = {
130 .request = npcm_reset_request,
131 .rfree = npcm_reset_free,
132 .rst_assert = npcm_reset_assert,
133 .rst_deassert = npcm_reset_deassert,
134 .of_xlate = npcm_reset_xlate,
135};
136
137U_BOOT_DRIVER(npcm_reset) = {
138 .name = "npcm_reset",
139 .id = UCLASS_RESET,
140 .of_match = npcm_reset_ids,
141 .bind = npcm_reset_bind,
142 .probe = npcm_reset_probe,
143 .ops = &npcm_reset_ops,
144 .priv_auto = sizeof(struct npcm_reset_priv),
145};